perl-modperl-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sbek...@hyperreal.org
Subject cvs commit: modperl-site/guide advocacy.html CHANGES all.html config.html control.html databases.html dbm.html debug.html guide-src.tar.gz guide.tar.gz hardware.html help.html index.html install.html modules.html multiuser.html obvious.html performance.html perl.html porting.html scenario.html security.html snippets.html status.html strategy.html warnings.html
Date Sat, 05 Jun 1999 17:47:54 GMT
sbekman     99/06/05 10:47:52

  Modified:    guide    CHANGES all.html config.html control.html
                        databases.html dbm.html debug.html guide-src.tar.gz
                        guide.tar.gz hardware.html help.html index.html
                        install.html modules.html multiuser.html
                        obvious.html performance.html perl.html
                        porting.html scenario.html security.html
                        snippets.html status.html strategy.html
                        warnings.html
  Added:       guide    advocacy.html
  Log:
  * install.pod: added "Should I rebuild mod_perl if I have upgraded my
    perl?"
  
  * scenario.pod: explained the long termed bug with APACI_ARGS, csh vs.
    sh issue.
  
  * databases.pod: added "mysql_use_result vs. mysql_store_result"
    (Michael Hall, Ken Williams, Vivek Khera)
  
  * config.pod: added "Logical grouping of Location, Directory and
    FilesMatch directives" (Daniel Koch)
  
  * config.pod: added "The confusion with use() clause in startup" file
    (Mike Fletcher)
  
  * config.pod: added "The confusion with defining globals in startup"
    file
  
  * performance.pod: extended the Devel::DProf notes with Apache::DProf
  
  * started a new advocacy.pod: mod_perl advocacy
  
  * install.pod: "Stripping apache to make it almost perl-server"
    (Jeffrey W. Baker, Randal L. Schwartz,Robin Berjon)
  
  * modules.pod, config.pod : added Doug's Apache::PerlVINC to set a
    different @INC perl location
  
  * install.pod: covered an installation problem of: "mod_perl.c is
    incompatible with this version of apache" (Doug)
  
  * databases.pod: added "Opening a connection with different
    parameters" (Jauder Ho, Edmund Mergl)
  
  * performance.pod. modules.pod - added Apache::GzipChain to cut down
    download times
  
  * debug.pod: added some snippets from Doug's replies showing strace
    and Devel::Peek in action
  
  * updated obvious.html#Reloading_only_specific_files - some code
    improvements (Ken Williams)
  
  * debug.pod: added "Debugging Signal Handlers ($SIG{FOO})" which
    covers the latest $SIG{ALRM} changes and Doug's Sys::Signal module
    to overcome the handler restore problem with other signals. (Doug)
  
  * strategy.pod: mod_proxy and http accell sections were extended by
    notes from Joshua Chamas.
  
  * warning.pod: noted a 'rwrite returned -1' fix in CVS version
  
  * obvious.pod: added "Additional reading references" to "my() scoped
    variable in nested subroutines" including a pointer to an article by
    Mark-Jason Dominus about how Perl handles variables and namespaces,
    and the difference between `use vars' and `my'.
  
  * hardware.pod: applied some addition and changes.
  
  * debug.pod: added "Monitoring error_log file"
  
  * scenario.pod: added a complete definition of ProxyReceiveBufferSize,
    its buffering functionality.
  
  * More pods have been purified by Steve Reppucci (hardware.pod,
    strategy.pod). Thanks to Steve English speakers can read my
    scribbles as well :o)
  
  Revision  Changes    Path
  1.12      +71 -1     modperl-site/guide/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/CHANGES,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- CHANGES	1999/05/17 20:47:26	1.11
  +++ CHANGES	1999/06/05 17:47:06	1.12
  @@ -1,5 +1,75 @@
   This is a CHANGES file for mod_perl guide
   
  +06.05.99 ver 1.12
  +
  +* install.pod: added "Should I rebuild mod_perl if I have upgraded my
  +  perl?"
  +
  +* scenario.pod: explained the long termed bug with APACI_ARGS, csh vs. 
  +  sh issue.
  +
  +* databases.pod: added "mysql_use_result vs. mysql_store_result"
  +  (Michael Hall, Ken Williams, Vivek Khera)
  +
  +* config.pod: added "Logical grouping of Location, Directory and
  +  FilesMatch directives" (Daniel Koch)
  +
  +* config.pod: added "The confusion with use() clause in startup" file
  +  (Mike Fletcher)
  +
  +* config.pod: added "The confusion with defining globals in startup"
  +  file
  +
  +* performance.pod: extended the Devel::DProf notes with Apache::DProf
  +
  +* started a new advocacy.pod: mod_perl advocacy
  +
  +* install.pod: "Stripping apache to make it almost perl-server"
  +  (Jeffrey W. Baker, Randal L. Schwartz,Robin Berjon)
  +
  +* modules.pod, config.pod : added Doug's Apache::PerlVINC to set a
  +  different @INC perl location
  +
  +* install.pod: covered an installation problem of: "mod_perl.c is
  +  incompatible with this version of apache" (Doug)
  +
  +* databases.pod: added "Opening a connection with different
  +  parameters" (Jauder Ho, Edmund Mergl)
  +
  +* performance.pod. modules.pod - added Apache::GzipChain to cut down
  +  download times
  +
  +* debug.pod: added some snippets from Doug's replies showing strace
  +  and Devel::Peek in action
  +
  +* updated obvious.html#Reloading_only_specific_files - some code
  +  improvements (Ken Williams)
  +
  +* debug.pod: added "Debugging Signal Handlers ($SIG{FOO})" which
  +  covers the latest $SIG{ALRM} changes and Doug's Sys::Signal module
  +  to overcome the handler restore problem with other signals. (Doug)
  +
  +* strategy.pod: mod_proxy and http accell sections were extended by
  +  notes from Joshua Chamas.
  +
  +* warning.pod: noted a 'rwrite returned -1' fix in CVS version
  +
  +* obvious.pod: added "Additional reading references" to "my() scoped 
  +  variable in nested subroutines" including a pointer to an article by
  +  Mark-Jason Dominus about how Perl handles variables and namespaces,
  +  and the difference between `use vars' and `my'.
  +
  +* hardware.pod: applied some addition and changes.
  +
  +* debug.pod: added "Monitoring error_log file"
  +
  +* scenario.pod: added a complete definition of ProxyReceiveBufferSize,
  +  its buffering functionality.
  +
  +* More pods have been purified by Steve Reppucci (hardware.pod,
  +  strategy.pod). Thanks to Steve English speakers can read my
  +  scribbles as well :o) 
  +
   05.17.99 ver 1.11
   
   * new hardware.pod: added a "Operating System and Hardware Demands"
  @@ -251,7 +321,7 @@
   * scenario.pod added : Is it possible to determine which options were
    given to modperl's Makefile.PL
   
  -* More pods has been purified by Steve Reppucci (warning.pod,
  +* More pods have been purified by Steve Reppucci (warning.pod,
    obvious.pod and porting.pod). He did so much work to make them
    readable, that I'm afraid to apply new changes to break all the
    beauty he made :) Thanks, Steve!
  
  
  
  1.13      +4839 -4087modperl-site/guide/all.html
  
  Index: all.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/all.html,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- all.html	1999/05/17 20:47:27	1.12
  +++ all.html	1999/06/05 17:47:07	1.13
  @@ -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.11
  - May, 17 1999</B></P></CENTER>
  +<CENTER><P><B>Version 1.12
  + Jun, 5 1999</B></P></CENTER>
    
   <P>
   <HR WIDTH="100%"></P>
  @@ -57,13 +57,13 @@
   
   	<LI><A HREF="start.html#What_s_inside_">What's inside?</A>
   </UL>
  -<P><LI><A HREF="strategy.html"><B><FONT SIZE=+1>Picking the Right Strategy</FONT></B></A></LI><P>
  +<P><LI><A HREF="strategy.html"><B><FONT SIZE=+1>Choosing the Right Strategy</FONT></B></A></LI><P>
   <UL>
   
   	<LI><A HREF="strategy.html#Do_it_like_me_">Do it like me?!</A>
  -	<LI><A HREF="strategy.html#mod_perl_Deploying_Schemas_Overv">mod_perl Deploying Schemas Overview</A>
  +	<LI><A HREF="strategy.html#mod_perl_Deployment_Overview">mod_perl Deployment Overview</A>
   	<LI><A HREF="strategy.html#Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A>
  -	<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_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>
  @@ -125,8 +125,11 @@
   	<UL>
   
   		<LI><A HREF="install.html#make_test_fails">make test fails</A>
  +		<LI><A HREF="install.html#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A>
  +		<LI><A HREF="install.html#Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A>
   	</UL>
   
  +	<LI><A HREF="install.html#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
   </UL>
   <P><LI><A HREF="config.html"><B><FONT SIZE=+1>Server Configuration</FONT></B></A></LI><P>
   <UL>
  @@ -145,6 +148,8 @@
   			<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>
   
   	</UL>
  @@ -161,12 +166,13 @@
   		<LI><A HREF="config.html#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="config.html#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="config.html#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="config.html#Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host basis. </A>
  +		<LI><A HREF="config.html#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="config.html#Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with</A>
   		<LI><A HREF="config.html#the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A>
   	</UL>
   
   	<LI><A HREF="config.html#Configuration_Security_Concerns">Configuration Security Concerns</A>
  +	<LI><A HREF="config.html#Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A>
   </UL>
   <P><LI><A HREF="frequent.html"><B><FONT SIZE=+1>Frequent mod_perl problems</FONT></B></A></LI><P>
   <UL>
  @@ -213,7 +219,7 @@
   	<LI><A HREF="porting.html#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
   	<UL>
   
  -		<LI><A HREF="porting.html#Sometimes_it_Works_Sometimes_Not">Sometimes it Works Sometimes Not (Very important!)</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>
   	</UL>
  @@ -265,36 +271,8 @@
   	<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#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="hardware.html"><B><FONT SIZE=+1>Choosing an Operating System and a Hardware</FONT></B></A></LI><P>
  -<UL>
  -
  -	<LI><A HREF="hardware.html#Is_it_important_">Is it important?</A>
  -	<LI><A HREF="hardware.html#Operating_System_Choosing">Operating System Choosing</A>
  -	<UL>
  -
  -		<LI><A HREF="hardware.html#Stability_and_Robustness">Stability and Robustness</A>
  -		<LI><A HREF="hardware.html#Memory_Management">Memory Management</A>
  -		<LI><A HREF="hardware.html#Memory_Leakages">Memory Leakages</A>
  -		<LI><A HREF="hardware.html#Sharing_Memory">Sharing Memory</A>
  -		<LI><A HREF="hardware.html#Cost_and_Support">Cost and Support</A>
  -		<LI><A HREF="hardware.html#Discontinued_products">Discontinued products</A>
  -		<LI><A HREF="hardware.html#OS_Releases">OS Releases</A>
  -	</UL>
  -
  -	<LI><A HREF="hardware.html#Hardware_Choosing">Hardware Choosing</A>
  -	<UL>
  -
  -		<LI><A HREF="hardware.html#Site_s_traffic">Site's traffic</A>
  -		<LI><A HREF="hardware.html#Cash">Cash</A>
  -		<LI><A HREF="hardware.html#IO_performance">IO performance</A>
  -		<LI><A HREF="hardware.html#Memory">Memory</A>
  -		<LI><A HREF="hardware.html#Internet_Connection">Internet Connection</A>
  -		<LI><A HREF="hardware.html#Bottlenecks">Bottlenecks</A>
  -		<LI><A HREF="hardware.html#Conclusion">Conclusion</A>
  -	</UL>
  -
  -</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>
   
  @@ -305,6 +283,7 @@
   		<LI><A HREF="obvious.html#The_poison">The poison</A>
   		<LI><A HREF="obvious.html#The_diagnosis">The diagnosis</A>
   		<LI><A HREF="obvious.html#The_remedy">The remedy</A>
  +		<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>
  @@ -319,11 +298,11 @@
   	<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>
   	<LI><A HREF="obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>
  -	<LI><A HREF="obvious.html#Handling_the_server_timeout_case">Handling the server timeout cases</A>
  +	<LI><A HREF="obvious.html#Handling_the_server_timeout_case">Handling the server timeout cases and working with $SIG{ALRM}</A>
   	<LI><A HREF="obvious.html#Where_do_the_warnings_errors_go_">Where do the warnings/errors go?</A>
   	<LI><A HREF="obvious.html#Setting_environment_variables_fo">Setting environment variables for scripts called from CGI.</A>
   </UL>
  -<P><LI><A HREF="warnings.html"><B><FONT SIZE=+1>Warnings and Errors: Where and Why.</FONT></B></A></LI><P>
  +<P><LI><A HREF="warnings.html"><B><FONT SIZE=+1>Runtime Warnings and Errors: Where and Why.</FONT></B></A></LI><P>
   <UL>
   
   	<LI><A HREF="warnings.html#General_Advice">General Advice </A>
  @@ -346,6 +325,20 @@
   	<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 to eat up all the disk's space, when it goes wild.</A>
  +</UL>
   <P><LI><A HREF="security.html"><B><FONT SIZE=+1>Protecting Your Site</FONT></B></A></LI><P>
   <UL>
   
  @@ -372,18 +365,20 @@
   		<UL>
   
   			<LI><A HREF="databases.html#The_morning_bug">The morning bug</A>
  +			<LI><A HREF="databases.html#Opening_a_connection_with_differ">Opening a connection with different parameters</A>
   			<LI><A HREF="databases.html#Cannot_find_the_DBI_handler">Cannot find the DBI handler</A>
   			<LI><A HREF="databases.html#Apache_DBI_does_not_work">Apache:DBI does not work</A>
   		</UL>
   
  -		<LI><A HREF="databases.html#Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A>
  -		<UL>
  +	</UL>
   
  -			<LI><A HREF="databases.html#Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A>
  -			<LI><A HREF="databases.html#My_DB_module">My::DB module</A>
  -			<LI><A HREF="databases.html#My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A>
  -		</UL>
  +	<LI><A HREF="databases.html#mysql_use_result_vs_mysql_store">mysql_use_result vs. mysql_store_result.</A>
  +	<LI><A HREF="databases.html#Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A>
  +	<UL>
   
  +		<LI><A HREF="databases.html#Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A>
  +		<LI><A HREF="databases.html#My_DB_module">My::DB module</A>
  +		<LI><A HREF="databases.html#My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A>
   	</UL>
   
   </UL>
  @@ -402,20 +397,6 @@
   	<LI><A HREF="multiuser.html#ISPs_providing_mod_perl_services">ISPs providing mod_perl services - a fantasy or reality.</A>
   	<LI><A HREF="multiuser.html#Virtual_Hosts_in_the_guide">Virtual Hosts in the guide</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 to eat up all the disk's space, when it goes wild.</A>
  -</UL>
   <P><LI><A HREF="status.html"><B><FONT SIZE=+1>mod_perl Status. Peeking into the Server's Perl Innards</FONT></B></A></LI><P>
   <UL>
   
  @@ -431,11 +412,15 @@
   <P><LI><A HREF="debug.html"><B><FONT SIZE=+1>Debugging mod_perl</FONT></B></A></LI><P>
   <UL>
   
  -	<LI><A HREF="debug.html#Sometimes_script_works_Sometime">Sometimes script works, Sometimes Not</A>
  +	<LI><A HREF="debug.html#Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A>
  +	<LI><A HREF="debug.html#Non_interactive_debugging_when_r">Non-interactive debugging when running under mod_perl</A>
   	<LI><A HREF="debug.html#Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A>
   	<LI><A HREF="debug.html#Debug_Tracing">Debug Tracing</A>
  -	<LI><A HREF="debug.html#Getting_some_decent_debug_info_w">Getting some decent debug info when running under mod_perl</A>
   	<LI><A HREF="debug.html#gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A>
  +	<LI><A HREF="debug.html#Monitoring_error_log_file">Monitoring error_log file</A>
  +	<LI><A HREF="debug.html#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
  +	<LI><A HREF="debug.html#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
  +	<LI><A HREF="debug.html#Devel_Peek">Devel::Peek</A>
   </UL>
   <P><LI><A HREF="browserbugs.html"><B><FONT SIZE=+1>Workarounds for some known bugs in browsers.</FONT></B></A></LI><P>
   <UL>
  @@ -450,6 +435,8 @@
   	<LI><A HREF="modules.html#Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A>
   	<LI><A HREF="modules.html#Apache_Request_libapreq_Gen">Apache::Request (libapreq) - Generic Apache Request Library</A>
   	<LI><A HREF="modules.html#Apache_PerlRun_Run_unaltered_">Apache::PerlRun - Run unaltered CGI scripts under mod_perl</A>
  +	<LI><A HREF="modules.html#Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A>
  +	<LI><A HREF="modules.html#Apache_PerlVINC_set_a_differe">Apache::PerlVINC - set a different @INC perl-location </A>
   </UL>
   <P><LI><A HREF="perl.html"><B><FONT SIZE=+1>Perl Reference</FONT></B></A></LI><P>
   <UL>
  @@ -475,6 +462,40 @@
   	<LI><A HREF="snippets.html#Accessing_variables_from_the_cal">Accessing variables from the caller's package</A>
   	<LI><A HREF="snippets.html#Handling_cookies">Handling cookies</A>
   </UL>
  +<P><LI><A HREF="hardware.html"><B><FONT SIZE=+1>Choosing an Operating System and Hardware</FONT></B></A></LI><P>
  +<UL>
  +
  +	<LI><A HREF="hardware.html#Is_it_important_">Is it important?</A>
  +	<LI><A HREF="hardware.html#Choosing_an_Operating_System">Choosing an Operating System</A>
  +	<UL>
  +
  +		<LI><A HREF="hardware.html#Stability_and_Robustness">Stability and Robustness</A>
  +		<LI><A HREF="hardware.html#Memory_Management">Memory Management</A>
  +		<LI><A HREF="hardware.html#Memory_Leakages">Memory Leakages</A>
  +		<LI><A HREF="hardware.html#Sharing_Memory">Sharing Memory</A>
  +		<LI><A HREF="hardware.html#Cost_and_Support">Cost and Support</A>
  +		<LI><A HREF="hardware.html#Discontinued_products">Discontinued products</A>
  +		<LI><A HREF="hardware.html#OS_Releases">OS Releases</A>
  +	</UL>
  +
  +	<LI><A HREF="hardware.html#Choosing_Hardware">Choosing Hardware</A>
  +	<UL>
  +
  +		<LI><A HREF="hardware.html#Site_traffic">Site traffic</A>
  +		<LI><A HREF="hardware.html#Cash">Cash</A>
  +		<LI><A HREF="hardware.html#Memory">Memory</A>
  +		<LI><A HREF="hardware.html#Internet_Connection">Internet Connection</A>
  +		<LI><A HREF="hardware.html#Bottlenecks">Bottlenecks</A>
  +		<LI><A HREF="hardware.html#Conclusion">Conclusion</A>
  +	</UL>
  +
  +</UL>
  +<P><LI><A HREF="advocacy.html"><B><FONT SIZE=+1>mod_perl Advocacy</FONT></B></A></LI><P>
  +<UL>
  +
  +	<LI><A HREF="advocacy.html#Thoughts_about_scalability">Thoughts about scalability</A>
  +	<LI><A HREF="advocacy.html#The_boss_and_the_developer">The boss and the developer</A>
  +</UL>
   <P><LI><A HREF="help.html"><B><FONT SIZE=+1>Getting Helped and Further Learning</FONT></B></A></LI><P>
   <UL>
   
  @@ -555,7 +576,7 @@
   <TR ALIGN=CENTER VALIGN=TOP>
   
   <TD ALIGN=CENTER VALIGN=CENTER><B><FONT SIZE=-1>Written by <A
  -HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 05/17/1999
  +HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 06/05/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>
  @@ -1114,7 +1135,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Picking the Right Strategy</TITLE>
  +   <TITLE>mod_perl guide: Choosing the Right Strategy</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -1136,16 +1157,16 @@
   <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>
  -Picking the Right Strategy</H1>
  +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 -->
   <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_Deploying_Schemas_Overv">mod_perl Deploying Schemas Overview</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_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>
  @@ -1169,27 +1190,27 @@
   <P>
   <CENTER><H1><A NAME="Do_it_like_me_">Do it like me?!</A></H1></CENTER>
   <P>
  -There is no such a thing as a <STRONG>RIGHT</STRONG> strategy in web server business, though there are the wrong ones. Never
  -believe a person, saying: <EM>"Do it this way, this is the best!"</EM>. As the old saying says: <EM>"Trust but verify"</EM>. There are too many technologies out there to pick from, and it might take
  -an enormous investment of time and money to try to validate each one,
  -before deciding what is your favorite one. Keeping this idea in mind, I
  -will try to present different combinations of mod_perl and other
  -technologies or just standalone mod_perl. How these things work together,
  -what are the good and what are the bad properties of each one, how hard to
  -install and maintain them, what approaches should be used and what to be
  -avoided.
  +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.
   
   <P>
  -To make myself clear, I would not talk about any technologies and tools,
  -but the ones complementing mod_perl.
  +To be clear, I will not address all technologies and tools, but limit this
  +discussion to those complementing mod_perl.
   
   <P>
  -Please let me stress it again: <STRONG>DO NOT</STRONG> blindly copy someone's setup and hope for a good. Choose what is best for
  -your situation. it might take _some_ effort to find it out.
  +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.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="mod_perl_Deploying_Schemas_Overv">mod_perl Deploying Schemas Overview</A></H1></CENTER>
  +<CENTER><H1><A NAME="mod_perl_Deployment_Overview">mod_perl Deployment Overview</A></H1></CENTER>
   <P>
   There are several different ways to build, configure and deploy your
   mod_perl enabled server. Some of them are:
  @@ -1197,70 +1218,73 @@
   <OL>
   <P><LI>
   <P>
  -Having 1 binary and 1 config file (one big binary for mod_perl)
  +Having one binary and one config file (one big binary for mod_perl).
   
   <P><LI>
   <P>
  -Having 2 binaries and 2 config files (one big binary for mod_perl and one
  -small for static object like images)
  +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 1 DSO style binary, mod_perl loadable object and 2 config files
  +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 week
  -documentation and is still subject to change and is rather more complex)
  +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 proxy server in the http accelerator mode.
  +Any of the above plus a reverse proxy server in http accelerator mode.
   
   </OL>
   <P>
  -If you are a newbie, I would recommend you to start with the first option
  -and work on getting your feet wet with apache and mod_perl, then decide
  -whether to move to the second one which allows a better tuning for the
  -price of more complicated administration or to the more
  -state-of-the-art-yet-suspiciously-new DSO system (third one) or/and to the
  -forth option which brings you even more power.
  +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.
   
   <P>
  -First option will kill your production site if you serve a lot of static
  -data with a 2-12 MB webservers. On the other hand while testing you will
  -have no other server interaction to mask or add to your errors.
  +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>
  -Second option allows you to seriously tune the two servers and get the
  -maximum performance. On the other hand you have to deal with proxying or
  -fancy site design to keep the two servers in step. Choose serving on
  -multiple ports, multiple IPs, etc... You also have to admimistrate one more
  -server.
  +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.
   
   <P>
  -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 even
  -shared amongst multiple servers. Again, it is bleeding edge and still sort
  -of platform wonky, but your milegue may vary. See <A HREF="././scenario.html#mod_perl_server_as_DSO">mod_perl server as DSO</A>.
  +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>.
   
   <P>
  -Forth option (proxy in http accelerator mode) - improves the performance by
  -caching and buffering, once correctly configured and tuned.
  +The fourth option (proxy in http accelerator mode), once correctly
  +configured and tuned, improves performance by caching and buffering page
  +results.
   
   <P>
  -The rest of this chapter discuss the pros and the cons of each of the
  -presented schemas. <A HREF="././scenario.html#">Real World Scenarios Implementaion</A>
  -describes the implementation techniques of described schemas.
  +The rest of this chapter discusses the pros and the cons of each of these
  +presented configurations.
  +<A HREF="././scenario.html#">Real World Scenarios Implementaion</A>
  +describes the implementation techniques of these schemas.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><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 to it the 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.
  +take your plain apache server and add mod_perl, like you add any other
  +apache module. You continue to run it at the port it was running before.
  +You probably want to try this before you proceed to more sophisticated and
  +complex techniques.
   
   <P>
   The Advantages:
  @@ -1268,16 +1292,18 @@
   <UL>
   <P><LI>
   <P>
  -Simplicity of installation. You just follow the installation instructions,
  -configure it, restart the server and you have finished.
  +Simplicity. You just follow the installation instructions, configure it,
  +restart the server and you are done.
   
   <P><LI>
   <P>
  -You do not have to think about using additional ports as we will see later.
  +No network changes. You do not have to worry about using additional ports
  +as we will see later.
   
  +<P><LI>
   <P>
  -You get a very fast server, you see an enormous speedup from the first
  -moment you have started to use it.
  +Speed. You get a very fast server, you see an enormous speedup from the
  +first moment you start to use it.
   
   </UL>
   <P>
  @@ -1286,43 +1312,48 @@
   <UL>
   <P><LI>
   <P>
  -A mod_perl process' size is huge compared to the plain apache you have got
  -used to (starting from 4Mb at the startup and growing to 10Mb and more,
  -depending on what and how do you use it). You probably have a few tens of
  -children processes. The memory adds up. Your memory demands are growing in
  -an order of magnitude. But this is something you will have to live with, if
  -you are in the mod_perl boat. Memory is cheap nowadays and the performance
  -boost mod_perl gives to your services worths every 100Mb of RAM you add.
  -
  -<P>
  -While you are calm to have these monsters to serve you scripts with the
  -monsters' speed, you should be very worried about them serving your static
  -objects, like images and html files. It means that if you will need more
  -processes to serve these - more memory, 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 a static object request
  -(or only one request if you have the
  -<CODE>KeepAlive</CODE> directive turned <CODE>ON</CODE>). 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.
  +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
  +
  +<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.
  +
  +<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.
   
   <P><LI>
   <P>
  -Another drawback that you cannot afford is having the huge process to wait
  -till the client with slow connection will receive the whole response. While
  -it might take a few milliseconds for your script to complete the request,
  -there is a chance it will be still busy for another 5 seconds or even
  -minutes if the request has come from the slow connection client. As in the
  -previous drawback, proxy comes to solve this problem. More on proxies
  -later.
  +Another drawback of this approach is that when serving output to a client
  +with a slow connection, the huge mod_perl-enabled server process (with all
  +of its system resources) will be tied up until the response is completely
  +written to the client. While it might take a few milliseconds for your
  +script to complete the request, there is a chance it will be still busy for
  +some number of seconds or even minutes if the request is from a slow
  +connection client. As in the previous drawback, a proxy solution can solve
  +this problem. More on proxies later.
   
   <P>
   Proxying dynamic content is not going to help much if all the clients are
  -on a fast local net. For example if you are an administrator of the
  -Intranet. On opposite, it can make things worse. But still remember that
  -some of your Intranet users might work from home through the slow modem
  -links.
  +on a fast local net (for example, if you are administering an Intranet.) On
  +the contrary, it can decrease performance. Still, remember that some of
  +your Intranet users might work from home through the slow modem links.
   
   </UL>
   <P>
  @@ -1330,8 +1361,8 @@
   started.
   
   <P>
  -Of course if your site is serving only the mod_perl scripts, this might be
  -the most perfect choice for you!
  +And of course, if your site is serving only mod_perl scripts, this might be
  +the perfect choice for you!
   
   <P>
   For implementation notes see :
  @@ -1341,22 +1372,22 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl enabled Apache Servers</A></H1></CENTER>
  +<CENTER><H1><A NAME="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 your scripts under mod_perl, you
  -will notice that the httpd processes consume a huge amount of memory, from
  -5M to 25M and more. That is the price you pay for the enormous speed
  +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.
   
   <P>
  -It is an overkill to serve static objects like images and html documents
  -with these large processes. The best 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 take care of requests to dynamic (generated)
  +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>
  -Since now on, I will refer to these two servers as <STRONG>httpd_docs</STRONG>
  +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>
  @@ -1365,23 +1396,28 @@
   <UL>
   <P><LI>
   <P>
  -Heavy mod_perl processes serving only dynamic requests. So we need much
  -less servers - memory requirements are drastically going down. While this
  -is always correct for static HTML object, you might still have a problem
  -with static object requests from the generated HTML. You must use a fully
  -qualified URL and not a relative one! When you generate an HTML which has
  -relative references to images or other static object - client's browser
  -sets its base url to point to
  -<CODE>httpd_perl</CODE> server's. And all the image requests will go to the heavy <CODE>httpd_perl</CODE>. Be aware! You solve this by either using a full URLs to the <CODE>httpd_docs</CODE> server (the fastest) or rewriting the requests back to <CODE>httpd_docs</CODE> (much 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>)
  +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>
   <P>
  -<CODE>MaxClients</CODE>, <CODE>MaxRequestsPerChild</CODE> and related parameters now can 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.
  +<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.
   
   <P>
  -Now we can spawn many light weighted <CODE>httpd_docs</CODE> servers and just a few heavy <CODE>httpd_perl</CODE> servers.
  +Now we can run many lightweight <CODE>httpd_docs</CODE> servers and just a few heavy <CODE>httpd_perl</CODE> servers.
   
   </UL>
   <P>
  @@ -1395,34 +1431,35 @@
   <UL>
   <P><LI>
   <P>
  -A need for 2 different configuration files, 2 log files sets and etc. We
  -need a special directories layout to manage these. While some directories
  -can be shared between the two servers, like <CODE>include</CODE>
  -directory, storing the apache include files (assuming that both are built
  -from the same source distribution), most of them should be separated and
  -configuration files updated to reflect the changes.
  +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.)
   
   <P><LI>
   <P>
  -A need for 2 sets of controlling scripts (startup/shutdown)
  +A need for two sets of controlling scripts (startup/shutdown)
   
   <P><LI>
   <P>
  -If you are processing log files, now you probably will have to merge the 2
  -separate log files.
  +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>
  -We still have the problem of mod_perl process spending its precious time to
  -server slow clients, when the request was processed long time ago, exactly
  -like in 1 server approach. Proxy solves this, and will be covered in the
  -next sections.
  +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>
  -Exactly as with only one server approach, this is not a disadvantage if you
  -are on the fast local Intranet. Most chances that you do not want a
  -buffering server on your way.
  +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>
  @@ -1435,9 +1472,9 @@
   <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 functionality needed from the the light server is static
  -objects serving, you can get away with non-apache servers, whose memory
  -footprint is even smaller. <CODE>thttpd</CODE> has been reported to be about 5 times faster then apache (especially under
  +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.
   
  @@ -1455,7 +1492,7 @@
   
   <P><LI>
   <P>
  -More memory saving. Apache is about 4 times bigger then <STRONG>thttpd</STRONG>, it if you spawn 30 children you use about 30M of memory, while <STRONG>thttpd</STRONG>
  +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.
   
  @@ -1471,8 +1508,8 @@
   <UL>
   <P><LI>
   <P>
  -Lucks some apache's features, like access control, error redirection,
  -logfile format and so on. 
  +Lacks some of apache's features, like access control, error redirection,
  +customizable logfile formats, and so on. 
   
   </UL>
   <P>
  @@ -1495,7 +1532,7 @@
   
   <P>
   Now I am going to convince you that you _want_ to use a proxy server (in
  -the http accelerator mode). The reasons are:
  +the http accelerator mode). The advantages are:
   
   <UL>
   <P><LI>
  @@ -1503,96 +1540,98 @@
   Allow serving of static objects from the proxy's cache (objects that
   previously were entirely served by the httpd_docs server). 
   
  +<P><LI>
   <P>
  -You get less I/O activity to read the object 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. (I/O
  -+1 points, faster static object serving +1 point)
  +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.
   
   <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 getting
  +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>
   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 a speed of
  -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 pretty average script that
  -generates this output in 0.5 secs. How much time the server will wait
  -before user will get the whole output down his way? A simple calculation
  -reveals pretty scaring numbers - it will have to wait for another 6 secs
  -(20kb/3.6kb), when it could serve another 12 (6/0.5) requests at the time
  -it was stalled. This very simple example shows us that we need 12 times
  -less children running, which means you will need 12 fold times less 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>
  -To make your numbers of download time 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 I was
  -talking about before, many times 5-10 times smaller.
  +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>
  +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.
   
  -<P>
  -(+3 point for memory cut up, I give it 3 times more points for the savings
  -we get with this most important functionality)
  -
   <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 serves as a front end,
  +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
  +other servers. (Of course this is pretty big topic, and it would not be
   included in the scope of this document)
   
  +<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.
  +
  +</UL>
   <P>
  -(+1 point for flexibility to change things at the background and making
  -user to bookmark only one URL)
  +The disadvantages are:
   
  +<UL>
   <P><LI>
   <P>
   Of course there are drawbacks. Luckily, these are not functionality
  -drawbacks, but more of administration hassle. Yes, you add another program
  -to worry about, 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. May be a watchdog script running at the
  +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.
   
  +<P><LI>
   <P>
  -Proxy servers can be configured to be light or heavy, admin must decide
  -what gives the highest performance for his application. Proxy server like
  +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 serving.
  +for faster service.
   
  -<P>
  -(-1 point for administration overhead, very small but overhead. -1 point
  -for memory consuming)
  -
   </UL>
   <P>
  -So let's sum up the points. We have 4 (6-2) points for the proxy server and
  -I believe I have succeeded to convince you, that you want it :)
  +Have I succeeded in convincing you that you want the proxy server?
   
   <P>
  -If you are on the local network, then the big benefit of 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.
  +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.
   
   <P>
  -As of this writing 2 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 2 of them.
  +As of this writing the two proxy implementations are known to be used in
  +bundle with mod_perl - <STRONG>squid</STRONG> proxy server and <STRONG>mod_proxy</STRONG> which is a part of the apache server. Let's compare the two of them.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -1603,17 +1642,17 @@
   <UL>
   <P><LI>
   <P>
  -Caching of static objects. So these are being served much faster taking
  +Caching of static objects. So these are being served much faster assuming
   that your cache size is big enough to keep the most requested objects in
   the cache.
   
   <P><LI>
   <P>
  -Buffering of dynamic content, by taking the burden of returning the
  -generated by mod_perl server content to the slow clients, thus freeing
  -mod_perl servers from wasteful waiting for the slow clients to download the
  -data. Freed servers immediately switch to serve other requests, thus your
  -number of required servers goes drastically down.
  +Buffering of dynamic content, by taking the burden of returning the content
  +generated by mod_perl servers to slow clients, thus freeing mod_perl
  +servers from waiting for the slow clients to download the data. Freed
  +servers immediately switch to serve other requests, thus your number of
  +required servers goes dramatically down.
   
   <P><LI>
   <P>
  @@ -1661,10 +1700,10 @@
   </UL>
   <P>
   The presented pros and cons lead to an idea, that probably you might want
  -squid more for its dynamic content buffering features, 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.
  +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>
   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
  @@ -1684,7 +1723,7 @@
   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 to fix redirects in a way that keeps the client's view of both
  +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
  @@ -1703,7 +1742,7 @@
   
   <P><LI>
   <P>
  -<CODE>ProxyPass</CODE> and <CODE>ProxyPassReverse</CODE> directives allows you to hide the internal redirects, so if <CODE>http://nowhere.com/modperl/</CODE> is actually
  +<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>
  @@ -1712,14 +1751,13 @@
   </PRE>
   <P><LI>
   <P>
  -It does mod_perl output buffering as squid. See the implementation notes
  -for more details
  +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><LI>
   <P>
   It even does caching. You have to produce correct <CODE>Content-Length</CODE>,
  -<CODE>Last-Modified</CODE> and <CODE>Expires</CODE> http headres for it to work. If some dynamic content is not to change
  -constantly, you can dramatically increase performance with caching it by
  +<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>
  @@ -1727,6 +1765,17 @@
   <CODE>ProxyPass</CODE> happens before the authentication phase, so you do not have to worry about
   authenticating twice.
   
  +<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>
  +The latest (from apache 1.3.6) Apache proxy accel mode reported to be very
  +stable.
  +
   </UL>
   <P>
   The Disadvantages:
  @@ -1760,7 +1809,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/04/1999
         </FONT>
       </B>
     </TD>
  @@ -2088,10 +2137,6 @@
   so we have to compile with the same compiler!!!
   
   <P>
  -Notice that <STRONG>ALL</STRONG>  <CODE>APACI_ARGS</CODE> (below) must be passed as one long line!!! I have wrapped them to allow
  -easier reading.
  -
  -<P>
   <PRE>  % cd /usr/src/httpd_perl/mod_perl-1.19
   </PRE>
   <P>
  @@ -2103,14 +2148,19 @@
     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,
  +  APACI_ARGS=--sbindir=/usr/local/sbin/httpd_perl, \
  +         --sysconfdir=/usr/local/etc/httpd_perl, \
  +         --localstatedir=/usr/local/var/httpd_perl, \
  +         --runtimedir=/usr/local/var/httpd_perl/run, \
  +         --logfiledir=/usr/local/var/httpd_perl/logs, \
            --proxycachedir=/usr/local/var/httpd_perl/proxy
   </PRE>
   <P>
  +Notice that <STRONG>ALL</STRONG>  <CODE>APACI_ARGS</CODE> (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.
  +
  +<P>
   As with <CODE>httpd_docs</CODE> you might need other modules like
   <CODE>mod_rewrite</CODE>, so add them here:
   
  @@ -2750,6 +2800,23 @@
   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.
  +
  +<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)
  +
  +<P>
  +Apache does caching as well. It's relevant to mod_perl only if you produce
  +proper headers so your scripts' output can be cached. See apache
  +documentation for more details on configuration of this capability.
  +
  +<P>
   Ask Bjoern Hansen has written a <CODE>mod_proxy_add_forward.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>
  @@ -2771,7 +2838,7 @@
   should be able to access REMOTE_ADDR as usual.
   
   <P>
  -IF you are using Apache::{Registry,PerlRun} - do it like this:
  +If you are using <CODE>Apache::{Registry,PerlRun}</CODE> - do it like this:
   
   <P>
   in startup.pl:
  @@ -2873,7 +2940,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/15/1999
  +	     <BR>Last Modified at 06/05/1999
         </FONT>
       </B>
     </TD>
  @@ -2952,8 +3019,11 @@
   	<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>
   	</UL>
   
  +	<LI><A HREF="#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -3010,7 +3080,7 @@
   
   <P>
   Here I will give only a short example of mod_perl installation. You should
  -read the real world scenarios for a more complete description.
  +read the <A HREF="././scenario.html#">Real World Scenarios Implementaion</A> for a more complete description.
   
   <P>
   As with any perl package, the installation of mod_perl is very easy and
  @@ -3334,6 +3404,43 @@
   <PRE>  make test
     make install
   </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.
  +
  +<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.
  +
  +<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!
  +
  +<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
  +better to build a fresh one to save you a mess.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</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>
  @@ -3357,7 +3464,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/15/1999
  +	     <BR>Last Modified at 06/05/1999
         </FONT>
       </B>
     </TD>
  @@ -3426,6 +3533,8 @@
   			<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>
  @@ -3442,12 +3551,13 @@
   		<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 basis. </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 -->
   
  @@ -3735,6 +3845,97 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="The_confusion_with_use_clause_">The confusion with use() clause at the server startup?</A></H3></CENTER>
  +<P>
  +Many people wonder, why there is a need for duplication of <CODE>use()</CODE>
  +clause both in startup file and in the script itself. The question rises
  +from misunderstanding of the <CODE>use()</CODE> operand. <CODE>use()</CODE> consists of two other operands, namely <CODE>require()</CODE> and <CODE>import()</CODE>. So when you write:
  +
  +<P>
  +<PRE>  use Foo qw(bar);
  +</PRE>
  +<P>
  +perl actually does:
  +
  +<P>
  +<PRE>  require Foo.pm;
  +  import qw(bar);
  +</PRE>
  +<P>
  +When you write:
  +
  +<P>
  +<PRE>  use Foo qw();
  +</PRE>
  +<P>
  +perl actually does:
  +
  +<P>
  +<PRE>  require Foo.pm;
  +  import qw();
  +</PRE>
  +<P>
  +which means that the caller does not want any symbols to be imported. Why
  +is this important? Since some modules has <CODE>@EXPORT</CODE> set to some tags to be exported by default and when 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.
  +
  +<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:
  +
  +<P>
  +<PRE>  package MyModule;
  +  
  +  sub {
  +    my $r = shift;
  +  
  +    ## Cool stuff goes here
  +  
  +    return OK;
  +  }
  +</PRE>
  +<P>
  +<PRE>  1;
  +</PRE>
  +<P>
  +You would either need to add:
  +
  +<P>
  +<PRE>  use Apache::Constants qw( OK );
  +</PRE>
  +<P>
  +Or instead of <CODE>return OK;</CODE> say:
  +
  +<P>
  +<PRE>  return Apache::Constants::OK;
  +</PRE>
  +<P>
  +See the manpage/perldoc on <CODE>Exporter</CODE> and <CODE>perlmod</CODE> for more on import.
  +
  +<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.
  +
  +<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.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Running_apachectl_configtest_o">Running 'apachectl configtest' or 'httpd -t'</A></H1></CENTER>
   <P>
   <CODE>apachectl configtest</CODE> tests the configuration file without starting the server. You can safely
  @@ -4073,12 +4274,17 @@
   
   <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 basis.</A></H2></CENTER>
  +<CENTER><H2><A NAME="Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host or per-location basis.</A></H2></CENTER>
   <P>
   You can use 'PerlSetEnv PERL5LIB ...' or a PerlFixupHandler w/ the lib
   pragma.
   
   <P>
  +Even a better way is to use <A HREF="././modules.html#Apache_PerlVINC_set_a_differe">Apache::PerlVINC</A>
  +
  +
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="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>
  @@ -4142,6 +4348,28 @@
   Another approach is to modify httpd sources to reveal no unwanted
   information, so if you know the port the <CODE>HEAD</CODE> request will return an empty or phony <CODE>Server:</CODE> field.
   
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A></H1></CENTER>
  +<P>
  +Let's say that you want all the file in a specific directory and below to
  +be handled the same way, but a few of them to be handled somewhat
  +different. For example:
  +
  +<P>
  +<PRE>  &lt;Directory /home/foo&gt;
  +    &lt;FilesMatch &quot;\.(html|txt)$&quot;&gt;
  +      SetHandler perl-script
  +      PerlHandler Apache::AddrMunge
  +    &lt;/FilesMatch&gt;
  +  &lt;/Directory&gt;
  +</PRE>
  +<P>
  +Alternatively you can use &lt;Files&gt; inside an <CODE>.htaccess</CODE> file.
  +
  +<P>
  +Note that you cannot have <CODE>Files</CODE> derective inside <CODE>Location</CODE>, but you can have <CODE>Files</CODE> inside <CODE>Directory</CODE>.
  +
   <P><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>
  @@ -4165,7 +4393,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/15/1999
  +	     <BR>Last Modified at 06/05/1999
         </FONT>
       </B>
     </TD>
  @@ -4376,7 +4604,7 @@
   	<LI><A HREF="#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
   	<UL>
   
  -		<LI><A HREF="#Sometimes_it_Works_Sometimes_Not">Sometimes it Works Sometimes Not (Very important!)</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>
   	</UL>
  @@ -4923,17 +5151,18 @@
   <PRE>  PerlTaintCheck On
   </PRE>
   <P>
  -Now, any and all code compiled inside httpd will be taint checked. 
  +Now, any and all code compiled inside httpd will be taint checked.
   
   <P>
   The environment variable PERL5OPT can be used to set additional perl
  -startup flags such as -d and -D. See perlrun.
  +startup flags such as -d and -D. See
  +<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>
   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> isn't <CODE>On</CODE>.
  +<CODE>PerlTaintCheck</CODE> is not <CODE>On</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -5373,7 +5602,7 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Sometimes_it_Works_Sometimes_Not">Sometimes it Works Sometimes Not (Very important!)</A></H2></CENTER>
  +<CENTER><H2><A NAME="Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it does Not (Very important!)</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
  @@ -5481,7 +5710,7 @@
     &lt;/Location&gt;
   </PRE>
   <P>
  -See <A HREF="#">Apache::PerlRun - a closer look</A>
  +See <A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
   
   
   
  @@ -5608,7 +5837,7 @@
       $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 error to be emailed to us, ofcourse -
  +    # 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) {
     
  @@ -5657,11 +5886,8 @@
     &lt;B&gt;Oops, An error has happened.&lt;/B&gt;&lt;P&gt;
       |;  
     
  -    print HTML::warn_box($message);
  +    print $message;
     
  -      # print the tail!
  -    HTML::custom_tail();
  -  
         # send email report if appropriate
       if ($should_email){
     
  @@ -5872,7 +6098,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/15/1999
  +	     <BR>Last Modified at 06/05/1999
         </FONT>
       </B>
     </TD>
  @@ -5923,7 +6149,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>
   Performance. Benchmarks.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="hardware.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <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>
   
  @@ -5966,6 +6192,7 @@
   	<LI><A HREF="#Using_1_under_mod_perl_and_be">Using $|=1 under mod_perl and better print() techniques.</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 -->
   
  @@ -7577,12 +7804,11 @@
   probably will want to optimize those, if your code is a way heavy.
   
   <P>
  -It is possible to profile code run under mod_perl with the Devel::DProf
  -module available on CPAN. However, you must have apache version 1.3b3 or
  -higher and the PerlChildExitHandler enabled. When the server is started,
  -Devel::DProf installs an END block to write the tmon.out file, which will
  -be run when the server is shutdown. Here is how to start and stop a server
  -with the profiler enabled:
  +It is possible to profile code run under mod_perl with the
  +<CODE>Devel::DProf</CODE> module available on CPAN. However, you must have apache version 1.3b3 or
  +higher and the PerlChildExitHandler enabled. When the server is started, <CODE>Devel::DProf</CODE> installs an END block to write the tmon.out file, which will be run when
  +the server is shutdown. Here is how to start and stop a server with the
  +profiler enabled:
   
   <P>
   <PRE>  % setenv PERL5OPT -d:DProf
  @@ -7593,12 +7819,25 @@
     % dprofpp
   </PRE>
   <P>
  -The Devel::DProf package is a Perl code profiler. This will collect
  -information on the execution time of a Perl script and of the subs in that
  -script. This information can be used to determine which subroutines are
  -using the most time and which subroutines are being called most often.
  +The <CODE>Devel::DProf</CODE> package is a Perl code profiler. This will collect information on the
  +execution time of a Perl script and of the subs in that script. This
  +information can be used to determine which subroutines are using the most
  +time and which subroutines are being called most often.
   
   <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>:
  +
  +<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.
  +
  +<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>
  @@ -7626,6 +7865,14 @@
   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="Sending_plain_HTML_as_a_compress">Sending plain HTML as a compressed output</A></H1></CENTER>
  +<P>
  +See <A HREF="././modules.html#Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A>
  +
  +
  +
   <P><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>
  @@ -7636,7 +7883,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="hardware.html">Next</A>      ]
  +	     [    <A HREF="porting.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>
  @@ -7649,7 +7896,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/05/1999
         </FONT>
       </B>
     </TD>
  @@ -7676,7 +7923,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Choosing an Operating System and a Hardware</TITLE>
  +   <TITLE>mod_perl guide: Things obvious to others, but not to you</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -7698,37 +7945,37 @@
   <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 an Operating System and a Hardware</H1>
  +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="obvious.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="performance.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="#Is_it_important_">Is it important?</A>
  -	<LI><A HREF="#Operating_System_Choosing">Operating System Choosing</A>
  +	<LI><A HREF="#Coverage">Coverage</A>
  +	<LI><A HREF="#my_scoped_variable_in_nested_s">my() scoped variable in nested subroutines</A>
   	<UL>
   
  -		<LI><A HREF="#Stability_and_Robustness">Stability and Robustness</A>
  -		<LI><A HREF="#Memory_Management">Memory Management</A>
  -		<LI><A HREF="#Memory_Leakages">Memory Leakages</A>
  -		<LI><A HREF="#Sharing_Memory">Sharing Memory</A>
  -		<LI><A HREF="#Cost_and_Support">Cost and Support</A>
  -		<LI><A HREF="#Discontinued_products">Discontinued products</A>
  -		<LI><A HREF="#OS_Releases">OS Releases</A>
  +		<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="#Hardware_Choosing">Hardware Choosing</A>
  +	<LI><A HREF="#Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A>
   	<UL>
   
  -		<LI><A HREF="#Site_s_traffic">Site's traffic</A>
  -		<LI><A HREF="#Cash">Cash</A>
  -		<LI><A HREF="#IO_performance">IO performance</A>
  -		<LI><A HREF="#Memory">Memory</A>
  -		<LI><A HREF="#Internet_Connection">Internet Connection</A>
  -		<LI><A HREF="#Bottlenecks">Bottlenecks</A>
  -		<LI><A HREF="#Conclusion">Conclusion</A>
  +		<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>
   </UL>
   <!-- INDEX END -->
   
  @@ -7746,865 +7993,399 @@
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Is_it_important_">Is it important?</A></H1></CENTER>
  +<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
   <P>
  -You can invest a lot of time and money into a server tuning and code
  -rewriting according the guidelines you have just learned, but your
  -performance will be really bad if you did not took into account the
  -hardware demands, and did not wisely chosen the operational system suited
  -for your needs. While tips below apply to any webserver, they are written
  -for a mod_perl enabled webservers' administrators.
  +This document describes ``special'' traps you may encounter when running
  +your plain CGIs under Apache::Registry and Apache::PerlRun.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Operating_System_Choosing">Operating System Choosing</A></H1></CENTER>
  -<P>
  -First lets talk about Operating Systems (OS). While personally I am a Linux
  -devotee, I do not want to start yet another OS war. Assuming this, I will
  -try to define what you should be looking for, then when you know what do
  -you want from your to be chosen OS, go find it. Enter the newsgroup of an
  -OS you think is a good candidate, and tell: ``I need an OS with good X,
  -fast Y and stable Z, do you think Foo OS answers all of my demands?'' I
  -will leave this fan research up to you. But I would use linux :) Just
  -kidding...
  -
  +<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="Stability_and_Robustness">Stability and Robustness</A></H2></CENTER>
  +<CENTER><H2><A NAME="The_poison">The poison</A></H2></CENTER>
   <P>
  -Probably the most important feature we want from OS is its stability and
  -robustness. We are into an Internet business, which does not have working
  -hours, like many conventional businesses we know about (9pm to 5pm). We are
  -open 24 hours a day. We can not afford off line periods, for our customers
  -will go shop for another service like ours, unless you have a monopoly :) .
  -If the OS of your choice crashes every day or so, I would throw it away,
  -after doing a little investigation, for there are might be a reason for a
  -system crash. Like a runaway server that eats up all the memory and disk,
  -so we cannot blame the OS for that. Generally people who use the OS for
  -some time can tell you a lot about its stability.
  +In a non modperl script (stand alone or CGI), there is no problem writing
  +code like this:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Memory_Management">Memory Management</A></H2></CENTER>
  +<PRE>    use CGI qw/param/;
  +    my $x = param('x');
  +    sub printit {
  +       print &quot;$x\n&quot;;
  +    }
  +</PRE>
   <P>
  -You want an OS with good memory management, for some OSes are well known as
  -memory hogs. The same code can use as twice as much memory on one OS
  -compared to the other. If the size of the mod_perl process is 10Mb and you
  -have tens of these running, it definitely adds up!
  +However, the script is run under Apache::Registry, it will in fact be
  +repackaged into something like this:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Memory_Leakages">Memory Leakages</A></H2></CENTER>
  +<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>
  -Some OSes and/or the libraries (like c libs) suffer from bad memory
  -leakages. You cannot afford such a system, for you are already know that a
  -single mod_perl process sometimes serves thousands of requests before it is
  -being put to death. So if the leaks add up on every request, your memory
  -demands will be huge. Of course your code can be guilty for the memory
  -leakages as well (check out the <CODE>Apache::Leak</CODE>
  -module). Certainly you can lower the number of requests to be served over
  -the process' life, but a performance degrade.
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Sharing_Memory">Sharing Memory</A></H2></CENTER>
   <P>
  -You want an OS with good sharing capabilities. As you have learned, if you
  -preload the modules and scripts at the server startup, they are being
  -shared between the spawned children, at least for a part of a process' life
  -span, since memory pages are getting ``dirty'' and ceasing to be shared.
  -This feature can save you up a lot of memory!!!
  +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="Cost_and_Support">Cost and Support</A></H2></CENTER>
  +<CENTER><H2><A NAME="The_diagnosis">The diagnosis</A></H2></CENTER>
   <P>
  -If you are into a big business you are not overly concerned about paying
  -$1000+ for some fancy OS and to get the bundled support for it. But if your
  -resources are low, you will look for a cheaper and free OSes. Free does not
  -mean bad, it can be quite the opposite as we all either know from our own
  -experience or read about in news. Free OSes can have and do have the best
  -support you can find. It is very easy to understand - most of the people
  -are not rich and will try to use a cheaper or free OS first if it does the
  -work for them. Since it really fits their needs, many people keep using it
  -and eventually know it quite good to provide a support for others in
  -trouble. Why would they do it for free? For a real spirit of the first days
  -of the Internet, when there was no commercial Internet and people helped
  -each other, because someone helped them in first place. I was there, I was
  -touched by that spirit and I will do anything to keep this spirit alive.
  +Always use -w (or/and PerlWarn ON)! Perl will then emit a warning like:
   
   <P>
  -But, lets back to our world. We are living in a material world, and our
  -bosses pay us to keep the systems running. So if you feel that you cannot
  -provide the support yourself and you do not trust the available free
  -resources, you must get an OS that have behind a company to pay for, and to
  -blame for any difficulties you might experience in hope that your cries for
  -help will be heard and answered. Your boss wants to be able to sue someone
  -if the project has a problem. If you buy a product and the company claims
  -support, then you have someone to sue. You do not have someone to sue other
  -than getting fired yourself if you go with Open Source and it fails.
  -
  +<PRE>  Value of $x will not stay shared at - line 5.
  +</PRE>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Discontinued_products">Discontinued products</A></H2></CENTER>
  +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)
  +
   <P>
  -You have invested a lot into a developing of some proprietary software,
  -that is bundled with the OS you were developing on and for. For example you
  -write some mod_perl handler that takes an advantage of some proprietary
  -features of the OS which make it faster and it will not run on any other
  -OS. Things are under control, the performance is great and you sing from
  -happiness. But... one day the company who wrote your beloved OS went
  -bankrupt, which is not unlikely to happen nowadays. You have got stuck with
  -their last masterpiece and no support! What are you going to do then?
  -Invest more into a porting of the software to another OS...
  +PERLDIAG manpage says:
   
   <P>
  -Everyone can be hit by this mini disaster, so it is better to watch the
  -background of the company when making your choice, but still you never know
  -what will happen in the next minute. The OSes in this hazard group are
  -developed completely by a single companies. Free OSes are probably more
  -promising for a development is distributed between many companies and
  -developers, so if a person who developed a really important part of the
  -kernel lost an interest to continue, someone else will pick up the falling
  -flag and continue from the same place. Of course if tomorrow some better
  -project will show up, developers might migrate there and finally drop the
  -development, but we are here not to let this happen.
  +<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>
  -But you are the one responsible for making the right decision...
  +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.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="OS_Releases">OS Releases</A></H2></CENTER>
  +<CENTER><H2><A NAME="The_remedy">The remedy</A></H2></CENTER>
   <P>
  -Actively developed OSes are generally tries to keep the pace with the
  -latest technology developments, and all the time optimize the kernel and
  -other parts of OS to become better and faster. Nowadays, Internet and
  -Networking in general are the most hot targets for system developers.
  -Sometimes a simple OS upgrade to a latest stable version, can save you an
  -expensive hardware upgrade. Also, remember that when you buy a new
  -hardware, chances are that latest software will take the most out of it.
  -Since while the existent software (drivers) might support the new product
  -because of its back compatibility with previous products of the same family
  -(brand), it might not take benefits of new features, so the you could spend
  -much less money for the same functionality if you were to buy a previous
  -model of the same product.
  +If a variable needs file scope, use a global variable:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Hardware_Choosing">Hardware Choosing</A></H1></CENTER>
  -<P>
  -While I am not fond of the idea of updating this section of the mod_perl
  -guide every day a new processor or memory type comes out, exactly like with
  -OS choosing guidelines, I will only hint what should you look for and
  -persuade you that sometimes the most expensive machine is not the one which
  -provides the best performance.
  -
  +<PRE>    use vars qw/$x/;
  +    use CGI qw/param/;
  +    $x = param('x');
  +    sub printit {
  +       print &quot;$x\n&quot;;
  +    }
  +</PRE>
   <P>
  -Your demands are bound to many aspects and components. Let's discuss some
  -of them.
  +You can safely use a <CODE>my()</CODE> scoped variable if its value is constant:
   
   <P>
  -In discussion course you might meet some unfamiliar terms, here are some of
  -them:
  -
  -<UL>
  -<P><LI>
  +<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>
  -Clustering - a bunch of machines connected together to perform one big or
  -many small computational tasks in a reasonable time.
  +Also see the clarification of <CODE>my()</CODE> vs. <CODE>use vars</CODE> - Ken Williams writes:
   
  -<P><LI>
   <P>
  -Balance loading - users can remember only a name of one of your machines -
  -namely of your server, but it cannot stand the heavy load, so you use a
  -clustering approach, distributing the load over a number of machines. The
  -central server, the one users access when they type the name of the
  -service, works as a dispatcher, by redirecting requests to the rest of the
  -machines, sometimes it also collects the results and return them to the
  -users. One of the advantages is that you can take one of the machines down
  -for a repair or upgrade, and your service will still work - the main server
  -will not dispatch the requests to the machine that was taken down. I will
  -just say that there are many load balancing techniques.
  -
  -<P><LI>
  +<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>
  -NIC - Network Interface Card.
  +And <CODE>my()</CODE> vs. <CODE>local()</CODE> - Randal Schwartz writes:
   
  -<P><LI>
   <P>
  -RAM - Random Access Memory
  -
  -<P><LI>
  +<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>
  -RAID - META
  +<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 `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>
  +.
   
  -</UL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Site_s_traffic">Site's traffic</A></H2></CENTER>
  +<CENTER><H1><A NAME="Reloading_Modules_and_Required_F">Reloading Modules and Required Files</A></H1></CENTER>
   <P>
  -If you are building a fans' site but want to amaze your friends with
  -mod_perl guest book, an old 486 machine will do. If you are into a serious
  -business, it is very important to build a scalable server, so if your
  -service is successful and becomes popular, you get your server's traffic
  -doubled every few days, you should be ready to add more resources
  -dynamically. While we can define the webserver scalability more precisely,
  -the important thing is to make sure that you can add more power to your
  -<CODE>webserver(s)</CODE> without investing additional money into a
  -software developing (almost, you will need a software to connect your
  -servers if you add more of them). It means that you should choose a
  -hardware/OS that can talk to other machines and become a part of the
  -cluster.
  +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>
  -From the other hand if you prepare for a big traffic and buy a monster to
  -do the work for you, what happens if your service does not prove to be as
  -successful as you thought it would be. Then you spent too much money and
  -meanwhile there were a new faster processors and other hardware components
  -released, so you loose again.
  +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>
  -Wisdom and prophecy , that's all it takes :)
  +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="Cash">Cash</A></H2></CENTER>
  +<CENTER><H2><A NAME="Restarting_the_server">Restarting the server</A></H2></CENTER>
   <P>
  -Everybody knows that Internet is a big cash hole, whatever you throw in,
  -hardly ever comes back. This is not always correct, but there is a lot of
  -wisdom in these words. While you have to invest money to build a decent
  -service, it can be cheaper! You can spend as much as 10 times more money on
  -a new strong machine, but to get only a 10% improvement in performance.
  -Remember that processor that was born 4 years ago is still very mighty.
  +See <A HREF="././control.html#Restarting_techniques">Server Restarting techniques</A>.
   
   <P>
  -If you really need a lot of power do not think about a strong machine
  -(unless you have money to throw away), think about clustering and load
  -balancing. You can probably buy 10 times more older but very cheap machines
  -and have a 8 times more power, then purchasing only one single newest
  -machine. Why is that? Because as I mentioned before generally the
  -performance improve is very marginal while the price is much bigger.
  -Because 10 machines will do a faster Hard Disk IO (Input/Output), then one
  -single machine even if the disk is much faster. Yes, you have more
  -administration overhead, but there is a chance you will have it anyway, for
  -in a short time the machine you have just invested into will not stand the
  -load and you will have to purchase more and to think how to implement the
  -load balancing and file system distribution.
  -
  +<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>
  -Why I am so convinced? Facts! Look at the most used services on the
  -Internet: search engines, email servers and alike - most of them are using
  -the clustering approach. While you are not always notice that, they do it
  -by hiding the real implementation behind the proxy servers.
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="IO_performance">IO performance</A></H2></CENTER>
   <P>
  -If your service is IO bound (does a lot of read/write operations to your
  -disk, remember that relational DataBases are sitting on disk as well) you
  -need a very fast disk. So you should not spend money on Video card and
  -monitor (monochrome card and 14`` B&amp;W will do for server
  -configuration), but to look for the best price/performance disks. Of course
  -you should ask around for a solid firm, whose HDs are not getting corrupted
  -at all. With money in hand you should think about getting a RAID system
  -(RAID is generally a box with many HDs, and it capable to read/write data
  -much faster. and is protected against disk corruptions, for it duplicates
  -the same data over a number of disks, so if one gets corrupted RAID detects
  -it and data is still correct on the duplicated disks.) You must think about
  -RAID or alike systems if you have an enormous data size to serve. (What is
  -enormous data size nowadays?).
  +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>
  -Ok, we have a fast disk, what's next? You need a fast disk controller. So
  -ether you should use the one coming on your motherboard or you should plug
  -a controller card if the one you have onboard is not good enough.
  +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="Memory">Memory</A></H2></CENTER>
  +<CENTER><H2><A NAME="Reloading_only_specific_files">Reloading only specific files</A></H2></CENTER>
   <P>
  -How much RAM do you need? Nowadays, most chances you will hear: ``Memory is
  -cheap, the more you buy the better''. But how much is enough? The answer
  -pretty straightforward: ``You do not want your machine to swap''. When CPU
  -needs to write something into a memory, but notices that it is already
  -full, it takes the least frequently used memory pages (4k/page on average
  -OS) and swap them out. Swapping out, means copying to the disk into a
  -special partition or file called swap and deleting from the real memory.
  -The another process asks CPU to bring another page, but CPU cannot find a
  -memory page in the RAM, it was just swapped out, so it goes and brings it
  -from the swap (swapping in). If memory is small, the swapping (in/out)
  -happens too frequently, CPU becomes too busy to bring the pages in and out,
  -HD working hard to read write the swapped out pages, and the whole
  -performance is going down. Sometimes your swap partition can become full as
  -well and your system might die.
  +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>
  -How do you make a decision? You know what is the highest page request rate
  -your service has and how long does an average request processing take. Now
  -you can calculate how many servers do you need. Knowing the how big any of
  -your servers can get, you know how much memory do you need. You probably
  -need less memory that you have calculated if your OS supports memory
  -sharing and you know how to deploy this feature (preloading the modules and
  -scripts at server's startup). Do not forget that other essential system's
  -processes need memory as well, so you should not plan for the webserver
  -only, but to take into an account all processes to be run on your system.
  -Remember that requests can be queued, so if you can afford your client to
  -wait a few moments, while some process gets free to serve it, your numbers
  -will be more correct, since you generally do not have the highest load, but
  -you should be ready to bear the picks. So you need to reserve at least 20%
  -of free memory for a pick situations. Many sites were reported to crash a
  -few moments after some scooping news about them were posted, and unexpected
  -number of requests suddenly came in. If you are about to announce something
  -cool, be aware of possible consequences.
  +Assuming that you start your script with loading <CODE>Foo::Bar</CODE> and importing some tags:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Internet_Connection">Internet Connection</A></H2></CENTER>
  +<PRE>  use lib &quot;/some/private/path&quot;;
  +  use Foo::Bar qw(:tags_group tag1 tag2);
  +</PRE>
   <P>
  -You have the best hardware you could get, but the service is still
  -crawling. Make sure you have a fast Internet connection. Not _fast_ as your
  -ISP claims it to be, but fast as it should be. The ISP might have a very
  -good connection to the Internet, but to put many clients on the same line,
  -and if these are heavy clients your traffic will have to share the same
  -line, thus the speed is getting down. Think about dedicated connection and
  -make sure it is truly dedicated, trust the ISP but check it!
  +Now to make a modification testing and reload at runtime you have to use
  +something like this:
   
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Bottlenecks">Bottlenecks</A></H2></CENTER>
   <P>
  -The most important thing to understand is that you might use the most
  -expensive components, but still get bad performance. Why? Let me introduce
  -you to this annoying term: A bottleneck.
  -
  +<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>
  -A machine is an aggregate of are many small and big components. Each one of
  -them can become a bottleneck. If you have a fast processor but not a great
  -deal of RAM, the processor will be under used waiting for the kernel to
  -swap in and out the memory pages, because memory is too small to fit at
  -least the most used ones. If you have a lot of memory and a fast processor
  -and a fast disk, but a slow controller - the performance will be poor, and
  -you will have wasted the money.
  +You may want to add debug print statements to debug this code in your
  +application.
   
   <P>
  -Of course use a NIC that does not create a bottleneck. If the NIC is slow,
  -the whole service is slow.
  +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><H2><A NAME="Conclusion">Conclusion</A></H2></CENTER>
  +<CENTER><H1><A NAME="Compiled_Regular_Expressions">Compiled Regular Expressions</A></H1></CENTER>
   <P>
  -To use your money optimally, you have either to understand your hardware
  -very well, so you will know what to pick or you should hire a knowledgeable
  -hardware consultant or employee it on a constant basis, since your demands
  -are probably being changed as time goes, and your HW should be adopted to
  -every change you do.
  +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:
   
  -<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="performance.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>
  -  <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/17/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: Things obvious to others, but not to you</TITLE>
  -   <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
  -   <META NAME="Author" CONTENT="Bekman Stas">
  -   <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>
  -Things obvious to others, but not to you</H1>
  -<HR WIDTH="100%">
  -	    [    <A HREF="hardware.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>
  -	</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</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 -->
  -
  -<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="Coverage">Coverage</A></H1></CENTER>
  +<PRE>  my $pat = '^foo$'; # likely to be input from an HTML form field
  +  foreach( @list ) {
  +    print if /$pat/o;
  +  }
  +</PRE>
   <P>
  -This document describes ``special'' traps you may encounter when running
  -your plain CGIs under Apache::Registry and Apache::PerlRun.
  +This is usually a big win in loops over lists, or when using
  +<STRONG>grep</STRONG> or <STRONG>map</STRONG>. 
   
  -<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>
  +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>
  -In a non modperl script (stand alone or CGI), there is no problem writing
  -code like this:
  +There are two solutions to this problem. 
   
   <P>
  -<PRE>    use CGI qw/param/;
  -    my $x = param('x');
  -    sub printit {
  -       print &quot;$x\n&quot;;
  -    }
  -</PRE>
  +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.
  +
   <P>
  -However, the script is run under Apache::Registry, it will in fact be
  -repackaged into something like this:
  +The above code fragment would be rewritten as: 
   
   <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>  my $pat = '^foo$';
  +  eval q{
  +    foreach( @list ) {
  +      print if /$pat/o;
       }
     }
   </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.
  +Just saying:
   
   <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.
  +<PRE>  eval q{ print if /$pat/o; };
  +</PRE>
  +<P>
  +is going to be a horribly expensive proposition. 
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="The_diagnosis">The diagnosis</A></H2></CENTER>
  +You can use this approach if you require more than one pattern match
  +operator in a given section of code. If the section contains only one
  +operator (be it an <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.
  +
   <P>
  -Always use -w (or/and PerlWarn ON)! Perl will then emit a warning like:
  +The above code fragment becomes: 
   
   <P>
  -<PRE>  Value of $x will not stay shared at - line 5.
  +<PRE>  my $pat = '^foo$';
  +  &quot;something&quot; =~ /$pat/; # dummy match (MUST NOT FAIL!)
  +  foreach( @list ) {
  +    print if //;
  +  }
   </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)
  +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>
  -PERLDIAG manpage says:
  +If you can guarantee that the pattern variable contains no meta-characters
  +(things like *, +, ^, $...), you can use the dummy match:
   
   <P>
  -<PRE>  An inner (nested) named subroutine is referencing a lexical variable
  -  defined in an outer subroutine.
  +<PRE>  &quot;$pat&quot; =~ /\Q$pat\E/; # guaranteed if no meta-characters present
   </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.
  +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>
  -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.
  +<PRE>  &quot;\377&quot; =~ /$pat|^[\377]$/; # guaranteed if meta-characters present
  +</PRE>
  +<P>
  +Phil. Chu contributed this:
   
   <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>
  +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>
  -If a variable needs file scope, use a global variable:
  +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>    use vars qw/$x/;
  -    use CGI qw/param/;
  -    $x = param('x');
  -    sub printit {
  -       print &quot;$x\n&quot;;
  -    }
  +<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>
  -You can safely use a <CODE>my()</CODE> scoped variable if its value is constant:
  +Example usage:
   
   <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>  @some_browsers = qw(Mozilla Lynx MSIE AmigaVoyager lwp libwww);
  +  $Known_Browser=Build_MatchMany_Function(@some_browsers);
   </PRE>
   <P>
  -Also see the clarification of <CODE>my()</CODE> vs. <CODE>use vars</CODE> - Ken Williams writes:
  -
  -<P>
  -<PRE>  Yes, there is quite a bit of difference!  With use vars(), you are
  -  making an entry in the symbol table, and you are telling the
  -  compiler that you are going to be referencing that entry without an
  -  explicit package name.
  -  
  -  With my(), NO ENTRY IS PUT IN THE SYMBOL TABLE.  The compiler
  -  figures out _at_ _compile_time_ which my() variables (i.e. lexical
  -  variables) are the same as each other, and once you hit execute time
  -  you can not go looking those variables up in the symbol table.
  -</PRE>
  -<P>
  -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>
  -<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> can add some (large?) overhead to server response times, and you certainly
  -wouldn't want Apache::StatINC module to be enabled in your production
  -site's configuration. But sometimes you want to have some Configuration
  -file (module) be reloaded without restarting the whole server. For this you
  -will have to add something like this in your code:
  -
  -<P>
  -Assume that you started your scripts with:
  -
  -<P>
  -<PRE>  use lib &quot;/some/private/path&quot;;
  -  use Foo::Bar qw(:subs);
  -</PRE>
  -<P>
  -Now to make a modification test and reload at runtime you have to use
  -something like this:
  -
  -<P>
  -<PRE>  # child's global variable to keep the timestamps 
  -  use vars qw(%MODIFIED);
  -  
  -  my $my_lib_root = &quot;/some/private/path&quot;;
  -  my $conf        = &quot;Foo/Bar.pm&quot;;
  -  my $conf_path   = &quot;$my_lib_root/$conf&quot;;
  -  
  -    # set modification time if it wasn't set before
  -    # Note: Use (stat $conf_path)[9] instead of -M test, if you reset
  -    # time with $^M=time
  -  $MODIFIED{$conf} ||= -M $conf_path;
  -  
  -    # now check whether it was changed (assuming the above wasn't
  -    # performed in this session
  -  if ($MODIFIED{$conf} != -M $conf_path){
  -      # only if deleted from %INC the require will be called below
  -    delete $INC{$conf};
  -  
  -        # this should be safe since @INC is being reset after we leave
  -        # the script, or you can skip this stage and require the script
  -        # with full path, remember that @INC now is different from the
  -        # one you have had when the script has been called at first time
  -    unshift @INC,$my_lib_root;
  -  
  -        # reread the file : use() wouldn't work here since it's compile time directive
  -    require Foo::Bar; 
  -  
  -        # now export the symbols (if you need them back :)
  -    import Foo::Bar qw(:subs);
  -  
  -        # Update the MODIFICATION times
  -    $MODIFIED{$conf} = -M $conf_path;
  -  }
  -</PRE>
  -<P>
  -You may want to add debug print statements to test this code in your
  -application. 
  -
  -<P>
  -Read the ``use versus require'' article for more info.
  -(http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require)
  -
  -<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
  -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
  -<STRONG>grep</STRONG> or <STRONG>map</STRONG>. 
  -
  -<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 <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.
  -
  -<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>  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 <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.
  -
  -<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 <STRONG>//</STRONG> 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>  #####################################################
  -  # 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>
  -Example usage:
  -
  -<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($_);
  @@ -8809,7 +8590,7 @@
   
   <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</A></H1></CENTER>
  +<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
  @@ -8828,30 +8609,10 @@
      
     die $@ if $@;
   </PRE>
  -<P>
  -But, as lately it was discovered <CODE>local $SIG{'ALRM'}</CODE> does not restore the original underlying C handler. Look at <CODE>Sys::Signal</CODE>
  -module, which should solve this problem.
  -
  -<P>
  -<CODE>Sys::Signal</CODE> - Set signal handlers with restoration of existing C sighandler
  -
  -<P>
  -Now use this code:
  -
  -<P>
  -<PRE>  use Sys::Signal ();
  -  eval {
  -    my $h = Sys::Signal-&gt;set(ALRM =&gt; sub { die &quot;timeout\n&quot; });
  -    alarm $timeout;
  -    ... do something thay may timeout ...
  -      alarm 0;
  -  };
  -  die $@ if $@;
  -</PRE>
   <P>
  -As of this writing it is still not entered CPAN and you can find it at <A
  -HREF="http://www.modperl.com/~dougm/perl/Sys-Signal-0.01.tar.gz">http://www.modperl.com/~dougm/perl/Sys-Signal-0.01.tar.gz</A>
  -. (But check the CPAN for the latest version anyway)
  +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>
  @@ -8952,7 +8713,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="hardware.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.html">Next</A>      ]
  +	     [    <A HREF="performance.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>
  @@ -8965,7 +8726,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/05/1999
         </FONT>
       </B>
     </TD>
  @@ -8992,7 +8753,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Warnings and Errors: Where and Why.</TITLE>
  +   <TITLE>mod_perl guide: Runtime Warnings and Errors: Where and Why.</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -9014,9 +8775,9 @@
   <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>
  -Warnings and Errors: Where and Why.</H1>
  +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="security.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <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>
   
  @@ -9089,7 +8850,10 @@
   see the rwrite messages if LogLevel is set to debug.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +This bug has been fixed in mod_perl 1.19_01 (CVS version).
  +
  +<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>
   <P>
   <PRE>  [modperl] caught SIGPIPE in process 1234
  @@ -9187,10 +8951,10 @@
   
   <P>
   <PRE> Looks like you have a $SIG{__DIE__} handler installed (Carp::confess?).
  - That's what's expected if so
  + That's what's expected if so.
   </PRE>
   <P>
  -It wasn't in my case, but may be yours 
  +It wasn't in my case, but may be yours. 
   
   <P>
   Bryan Miller said:
  @@ -9408,7 +9172,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="obvious.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="control.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -9421,7 +9185,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/04/1999
         </FONT>
       </B>
     </TD>
  @@ -9448,7 +9212,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Protecting Your Site</TITLE>
  +   <TITLE>mod_perl guide: Controlling and Monitoring the Server</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -9470,19 +9234,22 @@
   <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>
  -Protecting Your Site</H1>
  +Controlling and Monitoring the Server</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#An_Importance_of_Your_site_s_Sec">An Importance of Your site's Security</A>
  -	<LI><A HREF="#Illustrated_security_scenarios">Illustrated security scenarios</A>
  -	<UL>
  -
  -		<LI><A HREF="#Non_authenticated_access_for_int">Non authenticated access for internal IPs, but authenticated by external IPs</A>
  -	</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 to eat up all the disk's space, when it goes wild.</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -9500,795 +9267,1671 @@
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="An_Importance_of_Your_site_s_Sec">An Importance of Your site's Security</A></H1></CENTER>
  +<CENTER><H1><A NAME="Restarting_techniques">Restarting techniques</A></H1></CENTER>
   <P>
  -Lets state it, your site or service can easily become a target for some
  -Internet ``terrorists'', for something that you said, because of success
  -your site has, or for no obvious reason. Your site can be broken in, the
  -whole data can be deleted, some important information can be stolen, or a
  -much easier the site can be turned into a useless with a _simple_ Services
  -Deny Attack. What can you do about it? Protect yourself! Whatever you do,
  -your site will be still vulnerable as long as you are connected to the
  -network. Cut the connections down, turn off your machine and put it into a
  -safe - now it is more protected, but very useless.
  +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>
  -Let's first get acquainted with security related terminology:
  +<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:
   
  -<DL>
  -<P><DT><STRONG><A NAME="item_Authentication">Authentication</A></STRONG><DD>
   <P>
  -When you want to make sure that a user is the one he claims to be, you
  -generally ask her for a username and a password, right? Once you have both:
  -the username and the password, you can validate them in your database of
  -username/password pairs, and if both match - you know that user has passed
  -the <STRONG>Authentication</STRONG> stage. From this moment on if you keep the session open all you need is to
  -remember the username.
  +<PRE>  % ps auxc | grep httpd_perl
  +</PRE>
  +<P>
  +or maybe:
   
  -<P><DT><STRONG><A NAME="item_Authorization">Authorization</A></STRONG><DD>
   <P>
  -You might want to let user <STRONG>foo</STRONG> to access to some resource, but restrict her from accessing to another
  -resource, which in turn is accessible only for user <STRONG>bar</STRONG>. The process of checking access rights is being called <STRONG>Authorization</STRONG>. For <STRONG>Authorization</STRONG> all you need is a username or some other attribute you authorize upon. For
  -example you can authorize upon IP number, for example allowing only your
  -local users to use some service. Be warned that IP numbers or session_ids
  -can be spoofed, and that is why you would not do <STRONG>Authorization</STRONG>
  -without <STRONG>Authentication</STRONG>.
  +<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>
  -Actually you are familiar with both terms for a long time - when you telnet
  -to your account on some machine you go through a login process (<STRONG>Authentication</STRONG>). When you try to read some file on your file systems the kernel checks
  -first the permissions on this file. (you go through <STRONG>Authorization</STRONG>). That's why you could hear about <STRONG>Access
  -control</STRONG> which is another name for the same term.
  +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.
   
  -</DL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Illustrated_security_scenarios">Illustrated security scenarios</A></H1></CENTER>
  +<CENTER><H1><A NAME="Implications_of_sending_TERM_HU">Implications of sending TERM, HUP, and USR1 to the server</A></H1></CENTER>
   <P>
  -I am going to present some real world security requirements and their
  -implementations.
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Non_authenticated_access_for_int">Non authenticated access for internal IPs, but authenticated by external IPs</A></H2></CENTER>
  +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>
  -If you run an <STRONG>Extranet</STRONG> (Very similar to <STRONG>Intranet</STRONG> but partly accessible from the outside, e.g. read only) you might want to
  -let your internal users an non-restricted access to your web server, but if
  -these users are calling from the outside of your organization you want to
  -make sure these are your employees.
  +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>
  -First one is achieved very simply using the IP patterns of the organization
  -in a Perl Access Handler in an <CODE>.htaccess file</CODE>, which consequently sets the REMOTE_USER environmental variable to a
  -generic organization's username, so that certain scripts which rely on
  -<CODE>REMOTE_USER</CODE> environment variable will work properly.
  +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 second one should detect that the IP comes from the outside and user
  -should be authenticated, before allowed in.
  +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>
  -As you understood this is a pure authentication problem. Once user passes
  -the authentication, either bypassing it because of his IP address, or after
  -entering correct login/password pair, the
  -<CODE>REMOTE_USER</CODE> variable is being set. Now having it set we can talk about authorization.
  +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>
  -OK let's see the implementation. First we modify the &lt;httpd.conf&gt;:
  +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>
  -<PRE>  PerlModule My::Auth
  -  
  -  &lt;Location /private&gt;
  -    PerlAccessHandler My::Auth::access_handler
  -    PerlSetVar Intranet &quot;100.100.100.1 =&gt; userA, 100.100.100.2 =&gt; userB&quot;
  -    PerlAuthenHandler My::Auth::authen_handler
  -    AuthName realm
  -    AuthType Basic
  -    Require valid-user
  -  &lt;/Location&gt;
  -</PRE>
  +The only difference between USR1 and HUP is that USR1 allows children to
  +complete any in-progress request prior to killing them off.
  +
   <P>
  -Now the code of My/Auth.pm:
  +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>    sub access_handler {
  +<PRE> PerlFreshRestart On              (in httpd.conf) 
   </PRE>
   <P>
  -<PRE>        my $r = shift;
  -</PRE>
  +Make sure you read <A HREF="././warnings.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>.
  +
  +</DL>
   <P>
  -<PRE>        unless ($r-&gt;some_auth_required) {
  -                $r-&gt;log_reason(&quot;No authentication has been configured&quot;);
  -                return FORBIDDEN;
  -        }
  -        # get list of IP addresses
  -        my %ips = split /\s*(?:=&gt;|,)\s*/, $r-&gt;dir_config(&quot;Intranet&quot;);
  -</PRE>
  +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>
  -<PRE>        if (my $user = $ips{$r-&gt;connection-&gt;remote_ip}) {
  -</PRE>
  +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>                # update connection record
  -                $r-&gt;connection-&gt;user($user);
  +<PRE>  #define SIGHUP     1    /* hangup, generated when terminal disconnects */ 
  +  #define SIGTERM   15    /* software termination signal */
  +  #define SIGUSR1   30    /* user defined signal 1 */
   </PRE>
   <P>
  -<PRE>                # do not ask for a password
  -                $r-&gt;set_handlers(PerlAuthenHandler =&gt; [\&amp;OK]);
  -        }
  -        return OK;
  -    }
  -    
  -    sub authen_handler {
  -</PRE>
  +<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>
  -<PRE>        my $r = shift;
  -</PRE>
  +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>
  -<PRE>        # get user's authentication credentials
  -        my ($res, $sent_pw) = $r-&gt;get_basic_auth_pw;
  -        return $res if $res != OK;
  -        my $user = $r-&gt;connection-&gt;user;
  -</PRE>
  +Start httpd
  +
   <P>
  -<PRE>        # authenticate through DBI
  -        my $reason = authen_dbi ($r, $user, $sent_pw, $niveau);
  +<PRE>        % /usr/apps/sbin/httpd_perl/apachectl start 
   </PRE>
   <P>
  -<PRE>        if ($reason) {
  -                $r-&gt;note_basic_auth_failure;
  -                $r-&gt;log_reason ($reason, $r-&gt;uri);
  -                return AUTH_REQUIRED;
  -        }
  -        return OK;
  -    }
  -    
  -    sub authen_dbi{
  -      my ($r, $user, $sent_pw, $niveau) = @_;
  -</PRE>
  +Stop httpd
  +
   <P>
  -<PRE>      # validate username/passwd
  +<PRE>        % /usr/apps/sbin/httpd_perl/apachectl stop
   </PRE>
   <P>
  -<PRE>      return 0 if (*PASSED*)
  -        
  -      return &quot;Failed for X reason&quot;;
  +Restart httpd if running by sending a SIGHUP or start if not running
  +
  +<P>
  +<PRE>        % /usr/apps/sbin/httpd_perl/apachectl restart
   </PRE>
   <P>
  -<PRE>    }
  +Do a graceful restart by sending a SIGUSR1 or start if not running
  +
  +<P>
  +<PRE>        % /usr/apps/sbin/httpd_perl/apachectl graceful    
   </PRE>
   <P>
  -Either implement your <CODE>authen_dbi()</CODE> routine, or replace
  -<CODE>authen_handler()</CODE> with any authentication handler such as
  -<CODE>Apache::AuthenDBI</CODE>.
  +Do a configuration syntax test:
   
   <P>
  -<CODE>access_handler()</CODE> sets <CODE>REMOTE_USER</CODE> to be either <CODE>userA</CODE> or
  -<CODE>userB</CODE> according on the IP, if non matched <CODE>PerlAuthenHandler</CODE> will be not set to OK, and the next Authentication stage will ask the user
  -for a login and password.
  +<PRE>        % /usr/apps/sbin/httpd_perl/apachectl configtest 
  +</PRE>
  +<P>
  +See the next section for the implication of the above calls.
   
  -<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="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>
  -  <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/17/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: mod_perl and Relational Databases</TITLE>
  -   <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
  -   <META NAME="Author" CONTENT="Bekman Stas">
  -   <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>
  -mod_perl and Relational Databases</H1>
  -<HR WIDTH="100%">
  -	    [    <A HREF="security.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="dbm.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  -<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  -<UL>
  -
  -	<LI><A HREF="#Why_Relational_SQL_Databases">Why Relational (SQL) Databases</A>
  -	<LI><A HREF="#Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A>
  -	<UL>
  -
  -		<LI><A HREF="#Introduction">Introduction</A>
  -		<LI><A HREF="#Configuration">Configuration</A>
  -		<LI><A HREF="#Preopening_DBI_connections">Preopening DBI connections</A>
  -		<LI><A HREF="#Debugging_Apache_DBI">Debugging Apache::DBI</A>
  -		<LI><A HREF="#Problems_and_solutions">Problems and solutions</A>
  -		<UL>
  -
  -			<LI><A HREF="#The_morning_bug">The morning bug</A>
  -			<LI><A HREF="#Cannot_find_the_DBI_handler">Cannot find the DBI handler</A>
  -			<LI><A HREF="#Apache_DBI_does_not_work">Apache:DBI does not work</A>
  -		</UL>
  -
  -		<LI><A HREF="#Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A>
  -		<UL>
  -
  -			<LI><A HREF="#Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A>
  -			<LI><A HREF="#My_DB_module">My::DB module</A>
  -			<LI><A HREF="#My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A>
  -		</UL>
  -
  -	</UL>
  -
  -</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="Why_Relational_SQL_Databases">Why Relational (SQL) Databases</A></H1></CENTER>
  +Replace 'httpd_perl' with 'httpd_docs' in the above calls to control the
  +httpd_docs server.
  +
   <P>
  -Nowadays millions of users surf the Internet. There are millions of
  -Terabytes of data laying around. To manipulate that data new smart
  -techniques and technologies were invented. One of the major inventions was
  -a relational database, which allows to search and modify huge data storages
  -in zero time. It uses <STRONG>SQL</STRONG> (Structured Query Language) to manipulate contents of these databases. Of
  -course once we started to use the web, we have found a need to write web
  -interfaces to these databases and CGI was and is the mostly used technology
  -for building such interfaces. The main limitation for a CGI script driving
  -a database versus application, is its statelessness - on every request the
  -CGI script has to initiate a connection to the database, when the request
  -is completed the connection is lost. <CODE>Apache::DBI</CODE> was written to remove this limitation. When you use it, you have a
  -persistent database connection over the process' life. As you understand
  -this possible only with CGI running under mod_perl enabled server, since
  -the child process does not quit when the request has been served. So when a
  -mod_perl script needs to _talk_ to a database, he starts _talking_ right
  -away, without initiating a database connection first, <CODE>Apache::DBI</CODE> worries to provide a valid connection immediately. Of course the are more
  -nuances, which will be talked about in the following sections.
  +There are other options for <STRONG>apachectl</STRONG>, use 'help' option to see them all.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A></H1></CENTER>
  +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>
  -This module initiates a persistent database connection. It is possible only
  -with mod_perl.
  +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><H2><A NAME="Introduction">Introduction</A></H2></CENTER>
  +<CENTER><H1><A NAME="SUID_start_up_scripts">SUID start-up scripts</A></H1></CENTER>
   <P>
  -When loading the DBI module (do not confuse this with the Apache::DBI
  -module) it looks if the environment variable GATEWAY_INTERFACE starts with
  -'CGI-Perl' and if the module Apache::DBI has been loaded. In this case
  -every connect request will be forwarded to the Apache::DBI module. This
  -looks if a database handle from a previous connect request is already
  -stored 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. In
  -other words when the script is run again from a child that has already (and
  -is still) connected, the host/username/password is checked against the
  -cache of open connections, and if one is available, uses that one. There is
  -no need to delete the disconnect statements from your code. They won't do
  -anything because the Apache::DBI module overloads the disconnect method
  -with a NOP (like an empty call).
  +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.
   
   <P>
  -You want to use this module if you are opening a <STRONG>few</STRONG> DB connections to the server. <CODE>Apache::DBI</CODE> will make them persistent per child, so if you have 10 children and each
  -opens 2 different connections you will have in total 20 opened persistent
  -connections. Thus after initial connect you will save up the connection
  -time for every connect request from your DBI module. Which is a huge
  -benefit for the mod_perl apache server with high traffic of users deploying
  -the relational DB.
  +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.
   
   <P>
  -As you understand you must NOT use this module if you are opening a special
  -connection for each of your users, since each of them will stay persistent
  -and in a short time the number of connections will be so big that your
  -machine will scream and die. If you want to use
  -<CODE>Apache::DBI</CODE> in both situations, as of this moment the only available solution is to run
  -2 mod_perl servers, one using
  -<CODE>Apache::DBI</CODE> and one not.
  -
  +<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><H2><A NAME="Configuration">Configuration</A></H2></CENTER>
  +<CENTER><H1><A NAME="Monitoring_the_Server_A_watchdo">Monitoring the Server. A watchdog.</A></H1></CENTER>
   <P>
  -After installing this module, the configuration is simple - add to the
  -<CODE>httpd.conf</CODE> the following directive.
  +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>
  -<PRE>  PerlModule Apache::DBI
  -</PRE>
   <P>
  -Note that it is important, to load this module before any other ApacheDBI
  -module !
  +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>
  -You can skip preloading <CODE>DBI</CODE>, since <CODE>Apache::DBI</CODE> does that. But there is no harm if you leave it in.
  +Crontab entry:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Preopening_DBI_connections">Preopening DBI connections</A></H2></CENTER>
  +<PRE>  0,30 * * * * /path/to/the/apache.watchdog &gt;/dev/null 2&gt;&amp;1
  +</PRE>
   <P>
  -If you want that when you call the script after server restart, the
  -connection will be already preopened, you should use
  -<CODE>connect_on_init()</CODE> method in the startup file to preload every connection you are going to
  -use. For example:
  +The script:
   
   <P>
  -<PRE>  Apache::DBI-&gt;connect_on_init
  -  (&quot;DBI:mysql:myDB::myserver&quot;,
  -   &quot;username&quot;,
  -   &quot;passwd&quot;,
  -   {
  -    PrintError =&gt; 1, # warn() on errors
  -    RaiseError =&gt; 0, # don't die on error
  -    AutoCommit =&gt; 1, # commit executes immediately
  -   }
  -  );
  +<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>
  -As noted before, it is wise to you this method only if you only want all of
  -apache to be able to connect to the database server as one user (or few
  -users).
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Debugging_Apache_DBI">Debugging Apache::DBI</A></H2></CENTER>
   <P>
  -If you are not sure this module is working as advertised, you should enable
  -the Debug mode in the startup script by:
  +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.
   
  -<P>
  -<PRE>  $Apache::DBI::DEBUG = 1;
  -</PRE>
   <P>
  -Since now on you will see in the <CODE>error.log</CODE> file when Apache::DBI initializes a connection and when it just returns it
  -from its cache. Use the following command to see it in the real time (your
  -<CODE>error.log</CODE> file might be locate at a different path):
  +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>
  -<PRE>  tail -f /usr/local/apache/logs/error_log
  -</PRE>
   <P>
  -I use <CODE>alias</CODE> (in <CODE>tcsh</CODE>) so I will not have to remember the path:
  +So we end up with crontab entry:
   
   <P>
  -<PRE>  alias err &quot;tail -f /usr/local/apache/logs/error_log&quot;
  +<PRE>  * * * * * /path/to/the/watchdog.pl &gt;/dev/null 2&gt;&amp;1
   </PRE>
   <P>
  -Another approach is to add to <CODE>httpd.conf</CODE> (which does the same):
  +And the watchdog itself:
   
   <P>
  -<PRE>  PerlModule Apache::DebugDBI
  +<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><H2><A NAME="Problems_and_solutions">Problems and solutions</A></H2></CENTER>
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="The_morning_bug">The morning bug</A></H3></CENTER>
  +<CENTER><H1><A NAME="Running_server_in_a_single_mode">Running server in a single mode</A></H1></CENTER>
   <P>
  -SQL server keeps the connection to the client open for a limited period of
  -time. So many developers were bitten by so called <STRONG>Morning
  -bug</STRONG> when every morning the first users to use the site were receiving:
  -<CODE>No Data Returned</CODE> message, but then everything worked as usual. The error caused by <CODE>Apache::DBI</CODE> returning a handle of the invalid connection (server closed it because of
  -timeout), and the script was dying on that error. The infamous and well
  -documented in the man page,
  -<CODE>ping()</CODE> method was introduced to solve this problem. But seems that people are
  -still being beaten by this problem. Another solution was found - to rise
  -the timeout parameter at the SQL server startup. Currently I startup <CODE>mySQL</CODE> server with <CODE>safe_mysql</CODE>
  -script, so I have updated it to use this option:
  +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>  nohup $ledir/mysqld [snipped other options] -O wait_timeout=172800
  +<PRE>  % /usr/apps/sbin/httpd_perl/httpd_perl -X
   </PRE>
   <P>
  -Where 172800 secs equal to 48 hours. And it works.
  +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>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Cannot_find_the_DBI_handler">Cannot find the DBI handler</A></H3></CENTER>
  -<P>
  -Q: I cannot find the handler name with which to manipulate my connection;
  -hence I seem to be unable to do anything to my database.
  +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).
   
   <P>
  -A: You did not use <CODE>DBI::connect()</CODE> as with usual DBI usage to get your <CODE>$dbh</CODE> database handler.
  -Using the <CODE>Apache::DBI</CODE> does not eliminate the need to write a proper <CODE>DBI</CODE> code. As the man page states - you should program as if you did not use <CODE>Apache::DBI</CODE> at all. <CODE>Apache::DBI</CODE> will override and return you a cached connection. And in case of <CODE>disconnect()</CODE> call it will be just ignored.
  +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.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Apache_DBI_does_not_work">Apache:DBI does not work</A></H3></CENTER>
  -<P>
  -Make sure you have it installed.
  -
  -<P>
  -Make sure you configured mod_perl with EVERYTHING=1.
  -
  +<CENTER><H1><A NAME="Starting_a_personal_server_for_e">Starting a personal server for each developer</A></H1></CENTER>
   <P>
  -Use the example script eg/startup.pl (remove the comment from the line
  +If you are the only developer working on the specific server:port - you
  +have no problems, since you have a complete control over the server.
  +However, many times you have a group of developers who need to concurrently
  +develop their own mod_perl scripts. This means that each one will want to
  +have control over the server - to kill it, to run it in single server mode,
  +to restart it again, etc., as well to have control over the location of the
  +log files and other configuration settings like <STRONG>MaxClients</STRONG>, etc. You can work around this problem by preparing a few httpd.conf file
  +and forcing each developer to use:
   
   <P>
  -<PRE>  #use Apache::DebugDBI;
  +<PRE>  httpd_perl -f /path/to/httpd.conf  
   </PRE>
   <P>
  -and adapt the connect string. Do not change anything in your scripts, for
  -using Apache::DBI.
  +I have approached it in other way. I have used the -Dparameter 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><H2><A NAME="Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A></H2></CENTER>
  +<PRE>  % http_perl -Dsbekman
  +</PRE>
   <P>
  -In this section you will find scripts, modules and code snippets to help
  -get yourself started to use relational Databases with mod_perl scripts.
  -Note that I work with <CODE>mysql</CODE> ( <A HREF="http://www.mysql.com">http://www.mysql.com</A> ), so the code
  -you will find will work out of box with mysql, if you use some other SQL
  -engine, it might work for you as well, or some changes should be applied.
  +In <CODE>httpd.conf</CODE> I wrote:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A></H3></CENTER>
  +<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>
  -Having to write many queries in my CGI scripts, made me to write a stand
  -alone module that saves me a lot of time in writing and debugging my code.
  -It also makes my scripts are much smaller and easier to read. I will
  -present the module here, afterwards examples will follow:
  +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>
  -Notice the <CODE>DESTROY</CODE> block at the end of the module, which makes various cleanups and allows
  -this module to be used under <CODE>mod_cgi</CODE> as well.
  +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:
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="My_DB_module">My::DB module</A></H3></CENTER>
  +<PRE>  PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid.sbekman
  +  HTTPD='/usr/apps/sbin/httpd_perl/httpd_perl -Dsbekman'
  +</PRE>
   <P>
  -(note that you will not find it on CPAN)
  +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>
  -<PRE>  package My::DB;
  -  
  -  use strict;
  -  use 5.004;
  -  
  -  use DBI;
  -  
  -  use vars qw(%c);
  -  
  -  %c =
  -    (
  -       # DB debug
  -     #db_debug   =&gt; 1,
  -     db_debug  =&gt; 0,
  -  
  -     db =&gt; {
  -          DB_NAME      =&gt; 'foo',
  -          SERVER       =&gt; 'localhost',
  -          USER         =&gt; 'put_username_here',
  -          USER_PASSWD  =&gt; 'put_passwd_here',
  -         },
  -  
  -    );
  -  
  -  use Carp qw(croak verbose);
  -  #local $SIG{__WARN__} = \&amp;Carp::cluck;
  -  
  -  # untaint the path by explicit setting
  -  local $ENV{PATH} = '/bin:/usr/bin';
  -  
  -  #######
  -  sub new {
  -    my $proto = shift;
  -    my $class = ref($proto) || $proto;
  -    my $self  = {};
  +The last thing was to let developers an option to run in single process
  +mode by:
  +
  +<P>
  +<PRE>  /usr/apps/sbin/httpd_perl/httpd_perl -Dsbekman -X
  +</PRE>
  +<P>
  +In addition to making life easier, we decided to use relative links
  +everywhere in the static docs (including the calls to CGIs). You may ask
  +how using the relative link you will get to the right server? Very simple -
  +we have utilized the mod_rewrite to solve our problems:
  +
  +<P>
  +In 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>  # 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]
     
  -      # connect to the DB, Apache::DBI worries to cache the connections
  -      # save into a dbh - Database handle object
  -    $self-&gt;{dbh} = DBI-&gt;connect(&quot;DBI:mysql:$c{db}{DB_NAME}::$c{db}{SERVER}&quot;,
  -                               $c{db}{USER},
  -                               $c{db}{USER_PASSWD},
  -                               {
  -                                PrintError =&gt; 1, # warn() on errors
  -                                RaiseError =&gt; 0, # don't die on error
  -                                AutoCommit =&gt; 1, # commit executes immediately
  -                               }
  -                              )
  -      or DBI-&gt;disconnect(&quot;Cannot connect to database: $DBI::errstr\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]
     
  -      # we want to die on errors if in debug mode
  -    $self-&gt;{dbh}-&gt;{RaiseError} = 1 if $c{'db_debug'};
  +  # all the rest
  +  RewriteCond  %{REQUEST_URI} ^/(perl|cgi-perl)  
  +  RewriteRule ^(.*)           <A HREF="http://ourserver.com:81/">http://ourserver.com:81/</A>$1 [R]
     
  -      # init the sth - Statement handle object
  -    $self-&gt;{sth} = '';
  +</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)
  +
  +<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>
  +
  +
  +<P>
  +Of course you have another problem: The cgi generates some html, which
  +should be called again. If it generates a URL with hard coded PORT the
  +above scheme will not work. There 2 solutions:
  +
  +<P>
  +First, generate relative URL so it will reuse the technique above, with
  +redirect (which is transparent for user) but it will not work if you have
  +something to POST (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
  +<CODE>cgi_base_url</CODE>. Again this will work if the user is authenticated.
  +
  +<P>
  +All this is good for development. It is better to use the full URLs in
  +production, since if you have a static form and the <CODE>Action</CODE> is relative but the static document located on another server, pressing the
  +form's submit will cause a redirect to mod_perl server, but all the form's
  +data will be lost during the redirect.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Wrapper_to_emulate_the_server_en">Wrapper to emulate the server environment</A></H1></CENTER>
  +<P>
  +Many times you start off debugging your script by running it from your
  +favorite shell. Sometimes you encounter a very weird situation when script
  +runs from the shell but dies when called as a CGI. The real problem lies in
  +the difference between the environment that is being used by your server
  +and your shell. An example can be a different perl path or having 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.
  +
  +<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.
  +
  +<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)
  +
  +<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. 
     
  -    bless ($self, $class);
  +  #
  +  # Usage: wrap.pl some_cgi.pl
  +  #
     
  -    $self;
  +  BEGIN{
  +    use vars qw($basedir);
  +    $basedir = &quot;/usr/apps&quot;;
     
  -  } # end of sub new
  +    # 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;
     
  -  ######################################################################
  -                 ###################################
  -                 ###                             ###
  -                 ###       SQL Functions         ###
  -                 ###                             ###
  -                 ###################################
  -  ######################################################################
  +    # process the passed params
  +  my $cgi = shift || '';
  +  my $params = (@ARGV) ? join(&quot; &quot;, @ARGV) : '';
     
  -  # print debug messages
  -  sub d{
  -     # we want to print in debug mode the trace
  -    print &quot;&lt;DT&gt;&lt;B&gt;&quot;.join(&quot;&lt;BR&gt;&quot;, @_).&quot;&lt;/B&gt;\n&quot; if $c{'db_debug'};
  +  die &quot;Usage:\n\t$0 some_cgi.pl\n&quot; unless $cgi;
     
  -  } # end of sub d
  +    # 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;
  +  }
     
  -  ######################################################################
  -  # return a count of matched rows, by conditions 
  -  #
  -  #  $count = sql_count_matched($table_name,\@conditions);
  -  #
  -  # conditions must be an array so we can path more than one column with
  -  # the same name.
  -  #
  -  #  @conditions =  ( column =&gt; ['comp_sign','value'],
  -  #                  foo    =&gt; ['&gt;',15],
  -  #                  foo    =&gt; ['&lt;',30],
  -  #                );
  -  #
  -  # The sub knows automatically to detect and quote strings
  -  #
  -  ##########################
  -  sub sql_count_matched{
  -    my $self    = shift;
  -    my $table   = shift || '';
  -    my $r_conds = shift || [];
  -  
  -      # we want to print in debug mode the trace
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
  -  
  -      # build the query
  -    my $do_sql = &quot;SELECT COUNT(*) FROM $table &quot;;
  -    my @where = ();
  -    for(my $i=0;$i&lt;@{$r_conds};$i=$i+2) {
  -      push @where, join &quot; &quot;,
  -        $$r_conds[$i],
  -        $$r_conds[$i+1][0],
  -        sql_quote(sql_escape($$r_conds[$i+1][1]));
  -    }
  -      # Add the where clause if we have one
  -    $do_sql .= &quot;WHERE &quot;. join &quot; AND &quot;, @where if @where;
  -  
  -    d(&quot;SQL: $do_sql&quot;);
  -  
  -      # do query
  -    $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
  -    $self-&gt;{sth}-&gt;execute();
  -    my ($count) = $self-&gt;{sth}-&gt;fetchrow_array;
  -  
  -    d(&quot;Result: $count&quot;);
  -  
  -    $self-&gt;{sth}-&gt;finish;
  -  
  -    return $count;
  -  
  -  } # end of sub sql_count_matched
  -  
  -  
  -  
  -  ######################################################################
  -  # return a single (first) matched value or undef, by conditions and
  -  # restrictions
  -  #
  -  # sql_get_matched_value($table_name,$column,\@conditions,\@restrictions);
  -  #
  -  # column is a name of the column
  -  #
  -  # conditions must be an array so we can path more than one column with
  -  # the same name.
  -  #  @conditions =  ( column =&gt; ['comp_sign','value'],
  -  #                  foo    =&gt; ['&gt;',15],
  -  #                  foo    =&gt; ['&lt;',30],
  -  #                );
  -  # The sub knows automatically to detect and quote strings
  -  #
  -  # restrictions is a list of restrictions like ('order by email')
  -  #
  -  ##########################
  -  sub sql_get_matched_value{
  -    my $self    = shift;
  -    my $table   = shift || '';
  -    my $column  = shift || '';
  -    my $r_conds = shift || [];
  -    my $r_restr = shift || [];
  -  
  -      # we want to print in debug mode the trace
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
  -  
  -      # build the query
  -    my $do_sql = &quot;SELECT $column FROM $table &quot;;
  -  
  -    my @where = ();
  -    for(my $i=0;$i&lt;@{$r_conds};$i=$i+2) {
  -      push @where, join &quot; &quot;,
  -        $$r_conds[$i],
  -        $$r_conds[$i+1][0],
  -        sql_quote(sql_escape($$r_conds[$i+1][1]));
  -    }
  -      # Add the where clause if we have one
  -    $do_sql .= &quot; WHERE &quot;. join &quot; AND &quot;, @where if @where;
  -  
  -      # restrictions (DONT put commas!)
  -    $do_sql .= &quot; &quot;. join &quot; &quot;, @{$r_restr} if @{$r_restr};
  -  
  -    d(&quot;SQL: $do_sql&quot;);
  -  
  -      # do query
  -    return $self-&gt;{dbh}-&gt;selectrow_array($do_sql);
  -  
  -  } # end of sub sql_get_matched_value
  +    # 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>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Log_Rotation">Log Rotation</A></H1></CENTER>
  +<P>
  +A little bit off topic but good to know and use with mod_perl where your
  +error_log can grow at a 10-100Mb per day rate if your scripts spit out lots
  +of warnings...
  +
  +<P>
  +To rotate the logs do:
  +
  +<P>
  +<PRE>  mv access_log access_log.renamed
  +  kill -HUP `cat httpd.pid`
  +  sleep 10; # allow some children to complete requests and logging
  +  # now it's safe to use access_log.renamed
  +  .....
  +</PRE>
  +<P>
  +The effect of SIGUSR1 and SIGHUP 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:
  +
  +<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;;
     
  -  ######################################################################
  -  # return a single row of first matched rows, by conditions and
  -  # restrictions. The row is being inserted into @results_row array
  -  # (value1,value2,...)  or empty () if non matched
  -  #
  -  # sql_get_matched_row(\@results_row,$table_name,\@columns,\@conditions,\@restrictions);
  -  #
  -  # columns is a list of columns to be returned (username, fname,...)
  -  #
  -  # conditions must be an array so we can path more than one column with
  -  # the same name.
  -  #  @conditions =  ( column =&gt; ['comp_sign','value'],
  -  #                  foo    =&gt; ['&gt;',15],
  -  #                  foo    =&gt; ['&lt;',30],
  -  #                );
  -  # The sub knows automatically to detect and quote strings
  -  #
  -  # restrictions is a list of restrictions like ('order by email')
  -  #
  -  ##########################
  -  sub sql_get_matched_row{
  -    my $self    = shift;
  -    my $r_row   = shift || {};
  -    my $table   = shift || '';
  -    my $r_cols  = shift || [];
  -    my $r_conds = shift || [];
  -    my $r_restr = shift || [];
  +  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;
     
  -      # we want to print in debug mode the trace
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
  +  # rename log files
  +  chdir $logs_dir;
  +  @ARGV = @logfiles;
  +  while (&lt;&gt;) {
  +    close ARGV;
  +  }
     
  -      # build the query
  -    my $do_sql = &quot;SELECT &quot;;
  -    $do_sql .= join &quot;,&quot;, @{$r_cols} if @{$r_cols};
  -    $do_sql .= &quot; FROM $table &quot;;
  +  # now restart the server so the logs will be restarted
  +  system $restart_command;
     
  -    my @where = ();
  -    for(my $i=0;$i&lt;@{$r_conds};$i=$i+2) {
  -      push @where, join &quot; &quot;,
  -        $$r_conds[$i],
  -        $$r_conds[$i+1][0],
  -        sql_quote(sql_escape($$r_conds[$i+1][1]));
  +  # compress log files
  +  foreach (@logfiles) {
  +      system &quot;$gzip_exec $_.$time&quot;;
  +  }
  +</PRE>
  +<P>
  +Randal L. Schwartz contributed this:
  +
  +<BLOCKQUOTE>
  +
  +<P>
  +Cron fires off setuid script called log-roller that looks like this:
  +
  +<P>
  +<PRE>    #!/usr/bin/perl -Tw
  +    use strict;
  +    use File::Basename;
  +    
  +    $ENV{PATH} = &quot;/usr/ucb:/bin:/usr/bin&quot;;
  +    
  +    my $ROOT = &quot;/WWW/apache&quot;; # names are relative to this
  +    my $CONF = &quot;$ROOT/conf/httpd.conf&quot;; # master conf
  +    my $MIDNIGHT = &quot;MIDNIGHT&quot;;  # name of program in each logdir
  +    
  +    my ($user_id, $group_id, $pidfile); # will be set during parse of conf
  +    die &quot;not running as root&quot; if $&gt;;
  +    
  +    chdir $ROOT or die &quot;Cannot chdir $ROOT: $!&quot;;
  +    
  +    my %midnights;
  +    open CONF, &quot;&lt;$CONF&quot; or die &quot;Cannot open $CONF: $!&quot;;
  +    while (&lt;CONF&gt;) {
  +      if (/^User (\w+)/i) {
  +        $user_id = getpwnam($1);
  +        next;
  +      }
  +      if (/^Group (\w+)/i) {
  +        $group_id = getgrnam($1);
  +        next;
  +      }
  +      if (/^PidFile (.*)/i) {
  +        $pidfile = $1;
  +        next;
  +      }
  +     next unless /^ErrorLog (.*)/i;
  +      my $midnight = (dirname $1).&quot;/$MIDNIGHT&quot;;
  +      next unless -x $midnight;
  +      $midnights{$midnight}++;
       }
  -      # Add the where clause if we have one
  -    $do_sql .= &quot; WHERE &quot;. join &quot; AND &quot;, @where if @where;
  -  
  -      # restrictions (DONT put commas!)
  -    $do_sql .= &quot; &quot;. join &quot; &quot;, @{$r_restr} if @{$r_restr};
  -  
  -    d(&quot;SQL: $do_sql&quot;);
  -  
  -      # do query
  -    @{$r_row} = $self-&gt;{dbh}-&gt;selectrow_array($do_sql);
  -  
  -  } # end of sub sql_get_matched_row
  +    close CONF;
  +    
  +    die &quot;missing User definition&quot; unless defined $user_id;
  +    die &quot;missing Group definition&quot; unless defined $group_id;
  +    die &quot;missing PidFile definition&quot; unless defined $pidfile;
  +    
  +    open PID, $pidfile or die &quot;Cannot open $pidfile: $!&quot;;
  +    &lt;PID&gt; =~ /(\d+)/;
  +    my $httpd_pid = $1;
  +    close PID;
  +    die &quot;missing pid definition&quot; unless defined $httpd_pid and $httpd_pid;
  +    kill 0, $httpd_pid or die &quot;cannot find pid $httpd_pid: $!&quot;;
  +    
  +    
  +    for (sort keys %midnights) {
  +      defined(my $pid = fork) or die &quot;cannot fork: $!&quot;;
  +      if ($pid) {
  +        ## parent:
  +        waitpid $pid, 0;
  +      } else {
  +        my $dir = dirname $_;
  +        ($(,$)) = ($group_id,$group_id);
  +        ($&lt;,$&gt;) = ($user_id,$user_id);
  +        chdir $dir or die &quot;cannot chdir $dir: $!&quot;;
  +        exec &quot;./$MIDNIGHT&quot;;
  +        die &quot;cannot exec $MIDNIGHT: $!&quot;;
  +      }
  +    }
  +    
  +    kill 1, $httpd_pid or die &quot;Cannot sighup $httpd_pid: $!&quot;;
  +</PRE>
  +<P>
  +And then individual MIDNIGHT scripts can look like this:
  +
  +<P>
  +<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="Preventing_from_modperl_process_">Preventing from modperl process to eat up all the disk's space, when it goes wild.</A></H1></CENTER>
  +<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>
  +<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>
  +It seems that his script will trigger restart every minute, since once the
  +logfile grows to be of 100000 lines, it will stay of this size, unless you
  +remove or rename it, before you do restart. On my server I run a watchdog
  +every five minutes which restarts the server if it is getting stuck (it
  +always works since when some modperl child process goes wild, the I/O it
  +causes is so heavy that other brother processes cannot normally to serve
  +the requests.) See <A HREF="././control.html#Monitoring_the_Server_A_watchdo">Monitoring the Server</A> for more hints.
  +
  +<P>
  +Also check out the daemontools from <A
  +HREF="ftp://koobera.math.uic.edu/www/daemontools.html">ftp://koobera.math.uic.edu/www/daemontools.html</A>
  +
  +
  +<P>
  +<PRE>  ,-----
  +  | cyclog writes a log to disk. It automatically synchronizes the log
  +  | every 100KB (by default) to guarantee data integrity after a crash. It
  +  | automatically rotates the log to keep it below 1MB (by default). If
  +  | the disk fills up, cyclog pauses and then tries again, without losing
  +  | any data.
  +  `-----
  +</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +	     The <a href="http://www.modperl.com/">
  +	     <B>Writing Apache Modules with Perl and C</B></a>
  +	     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="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]
  +
  +<CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
  +<TR ALIGN=CENTER VALIGN=TOP>
  +  <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/04/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: Protecting Your Site</TITLE>
  +   <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
  +   <META NAME="Author" CONTENT="Bekman Stas">
  +   <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>
  +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 -->
  +<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  +<UL>
  +
  +	<LI><A HREF="#An_Importance_of_Your_site_s_Sec">An Importance of Your site's Security</A>
  +	<LI><A HREF="#Illustrated_security_scenarios">Illustrated security scenarios</A>
  +	<UL>
  +
  +		<LI><A HREF="#Non_authenticated_access_for_int">Non authenticated access for internal IPs, but authenticated by external IPs</A>
  +	</UL>
  +
  +</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="An_Importance_of_Your_site_s_Sec">An Importance of Your site's Security</A></H1></CENTER>
  +<P>
  +Lets state it, your site or service can easily become a target for some
  +Internet ``terrorists'', for something that you said, because of success
  +your site has, or for no obvious reason. Your site can be broken in, the
  +whole data can be deleted, some important information can be stolen, or a
  +much easier the site can be turned into a useless with a _simple_ Services
  +Deny Attack. What can you do about it? Protect yourself! Whatever you do,
  +your site will be still vulnerable as long as you are connected to the
  +network. Cut the connections down, turn off your machine and put it into a
  +safe - now it is more protected, but very useless.
  +
  +<P>
  +Let's first get acquainted with security related terminology:
  +
  +<DL>
  +<P><DT><STRONG><A NAME="item_Authentication">Authentication</A></STRONG><DD>
  +<P>
  +When you want to make sure that a user is the one he claims to be, you
  +generally ask her for a username and a password, right? Once you have both:
  +the username and the password, you can validate them in your database of
  +username/password pairs, and if both match - you know that user has passed
  +the <STRONG>Authentication</STRONG> stage. From this moment on if you keep the session open all you need is to
  +remember the username.
  +
  +<P><DT><STRONG><A NAME="item_Authorization">Authorization</A></STRONG><DD>
  +<P>
  +You might want to let user <STRONG>foo</STRONG> to access to some resource, but restrict her from accessing to another
  +resource, which in turn is accessible only for user <STRONG>bar</STRONG>. The process of checking access rights is being called <STRONG>Authorization</STRONG>. For <STRONG>Authorization</STRONG> all you need is a username or some other attribute you authorize upon. For
  +example you can authorize upon IP number, for example allowing only your
  +local users to use some service. Be warned that IP numbers or session_ids
  +can be spoofed, and that is why you would not do <STRONG>Authorization</STRONG>
  +without <STRONG>Authentication</STRONG>.
  +
  +<P>
  +Actually you are familiar with both terms for a long time - when you telnet
  +to your account on some machine you go through a login process (<STRONG>Authentication</STRONG>). When you try to read some file on your file systems the kernel checks
  +first the permissions on this file. (you go through <STRONG>Authorization</STRONG>). That's why you could hear about <STRONG>Access
  +control</STRONG> which is another name for the same term.
  +
  +</DL>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Illustrated_security_scenarios">Illustrated security scenarios</A></H1></CENTER>
  +<P>
  +I am going to present some real world security requirements and their
  +implementations.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Non_authenticated_access_for_int">Non authenticated access for internal IPs, but authenticated by external IPs</A></H2></CENTER>
  +<P>
  +If you run an <STRONG>Extranet</STRONG> (Very similar to <STRONG>Intranet</STRONG> but partly accessible from the outside, e.g. read only) you might want to
  +let your internal users an non-restricted access to your web server, but if
  +these users are calling from the outside of your organization you want to
  +make sure these are your employees.
  +
  +<P>
  +First one is achieved very simply using the IP patterns of the organization
  +in a Perl Access Handler in an <CODE>.htaccess file</CODE>, which consequently sets the REMOTE_USER environmental variable to a
  +generic organization's username, so that certain scripts which rely on
  +<CODE>REMOTE_USER</CODE> environment variable will work properly.
  +
  +<P>
  +The second one should detect that the IP comes from the outside and user
  +should be authenticated, before allowed in.
  +
  +<P>
  +As you understood this is a pure authentication problem. Once user passes
  +the authentication, either bypassing it because of his IP address, or after
  +entering correct login/password pair, the
  +<CODE>REMOTE_USER</CODE> variable is being set. Now having it set we can talk about authorization.
  +
  +<P>
  +OK let's see the implementation. First we modify the &lt;httpd.conf&gt;:
  +
  +<P>
  +<PRE>  PerlModule My::Auth
  +  
  +  &lt;Location /private&gt;
  +    PerlAccessHandler My::Auth::access_handler
  +    PerlSetVar Intranet &quot;100.100.100.1 =&gt; userA, 100.100.100.2 =&gt; userB&quot;
  +    PerlAuthenHandler My::Auth::authen_handler
  +    AuthName realm
  +    AuthType Basic
  +    Require valid-user
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +Now the code of My/Auth.pm:
  +
  +<P>
  +<PRE>    sub access_handler {
  +</PRE>
  +<P>
  +<PRE>        my $r = shift;
  +</PRE>
  +<P>
  +<PRE>        unless ($r-&gt;some_auth_required) {
  +                $r-&gt;log_reason(&quot;No authentication has been configured&quot;);
  +                return FORBIDDEN;
  +        }
  +        # get list of IP addresses
  +        my %ips = split /\s*(?:=&gt;|,)\s*/, $r-&gt;dir_config(&quot;Intranet&quot;);
  +</PRE>
  +<P>
  +<PRE>        if (my $user = $ips{$r-&gt;connection-&gt;remote_ip}) {
  +</PRE>
  +<P>
  +<PRE>                # update connection record
  +                $r-&gt;connection-&gt;user($user);
  +</PRE>
  +<P>
  +<PRE>                # do not ask for a password
  +                $r-&gt;set_handlers(PerlAuthenHandler =&gt; [\&amp;OK]);
  +        }
  +        return OK;
  +    }
  +    
  +    sub authen_handler {
  +</PRE>
  +<P>
  +<PRE>        my $r = shift;
  +</PRE>
  +<P>
  +<PRE>        # get user's authentication credentials
  +        my ($res, $sent_pw) = $r-&gt;get_basic_auth_pw;
  +        return $res if $res != OK;
  +        my $user = $r-&gt;connection-&gt;user;
  +</PRE>
  +<P>
  +<PRE>        # authenticate through DBI
  +        my $reason = authen_dbi ($r, $user, $sent_pw, $niveau);
  +</PRE>
  +<P>
  +<PRE>        if ($reason) {
  +                $r-&gt;note_basic_auth_failure;
  +                $r-&gt;log_reason ($reason, $r-&gt;uri);
  +                return AUTH_REQUIRED;
  +        }
  +        return OK;
  +    }
  +    
  +    sub authen_dbi{
  +      my ($r, $user, $sent_pw, $niveau) = @_;
  +</PRE>
  +<P>
  +<PRE>      # validate username/passwd
  +</PRE>
  +<P>
  +<PRE>      return 0 if (*PASSED*)
  +        
  +      return &quot;Failed for X reason&quot;;
  +</PRE>
  +<P>
  +<PRE>    }
  +</PRE>
  +<P>
  +Either implement your <CODE>authen_dbi()</CODE> routine, or replace
  +<CODE>authen_handler()</CODE> with any authentication handler such as
  +<CODE>Apache::AuthenDBI</CODE>.
  +
  +<P>
  +<CODE>access_handler()</CODE> sets <CODE>REMOTE_USER</CODE> to be either <CODE>userA</CODE> or
  +<CODE>userB</CODE> according on the IP, if non matched <CODE>PerlAuthenHandler</CODE> will be not set to OK, and the next Authentication stage will ask the user
  +for a login and password.
  +
  +<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="control.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>
  +  <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/17/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: mod_perl and Relational Databases</TITLE>
  +   <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
  +   <META NAME="Author" CONTENT="Bekman Stas">
  +   <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>
  +mod_perl and Relational Databases</H1>
  +<HR WIDTH="100%">
  +	    [    <A HREF="security.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="dbm.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  +<UL>
  +
  +	<LI><A HREF="#Why_Relational_SQL_Databases">Why Relational (SQL) Databases</A>
  +	<LI><A HREF="#Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A>
  +	<UL>
  +
  +		<LI><A HREF="#Introduction">Introduction</A>
  +		<LI><A HREF="#Configuration">Configuration</A>
  +		<LI><A HREF="#Preopening_DBI_connections">Preopening DBI connections</A>
  +		<LI><A HREF="#Debugging_Apache_DBI">Debugging Apache::DBI</A>
  +		<LI><A HREF="#Problems_and_solutions">Problems and solutions</A>
  +		<UL>
  +
  +			<LI><A HREF="#The_morning_bug">The morning bug</A>
  +			<LI><A HREF="#Opening_a_connection_with_differ">Opening a connection with different parameters</A>
  +			<LI><A HREF="#Cannot_find_the_DBI_handler">Cannot find the DBI handler</A>
  +			<LI><A HREF="#Apache_DBI_does_not_work">Apache:DBI does not work</A>
  +		</UL>
  +
  +	</UL>
  +
  +	<LI><A HREF="#mysql_use_result_vs_mysql_store">mysql_use_result vs. mysql_store_result.</A>
  +	<LI><A HREF="#Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A>
  +	<UL>
  +
  +		<LI><A HREF="#Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A>
  +		<LI><A HREF="#My_DB_module">My::DB module</A>
  +		<LI><A HREF="#My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A>
  +	</UL>
  +
  +</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="Why_Relational_SQL_Databases">Why Relational (SQL) Databases</A></H1></CENTER>
  +<P>
  +Nowadays millions of users surf the Internet. There are millions of
  +Terabytes of data laying around. To manipulate that data new smart
  +techniques and technologies were invented. One of the major inventions was
  +a relational database, which allows to search and modify huge data storages
  +in zero time. It uses <STRONG>SQL</STRONG> (Structured Query Language) to manipulate contents of these databases. Of
  +course once we started to use the web, we have found a need to write web
  +interfaces to these databases and CGI was and is the mostly used technology
  +for building such interfaces. The main limitation for a CGI script driving
  +a database versus application, is its statelessness - on every request the
  +CGI script has to initiate a connection to the database, when the request
  +is completed the connection is lost. <CODE>Apache::DBI</CODE> was written to remove this limitation. When you use it, you have a
  +persistent database connection over the process' life. As you understand
  +this possible only with CGI running under mod_perl enabled server, since
  +the child process does not quit when the request has been served. So when a
  +mod_perl script needs to _talk_ to a database, he starts _talking_ right
  +away, without initiating a database connection first, <CODE>Apache::DBI</CODE> worries to provide a valid connection immediately. Of course the are more
  +nuances, which will be talked about in the following sections.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A></H1></CENTER>
  +<P>
  +This module initiates a persistent database connection. It is possible only
  +with mod_perl.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Introduction">Introduction</A></H2></CENTER>
  +<P>
  +When loading the DBI module (do not confuse this with the Apache::DBI
  +module) it looks if the environment variable GATEWAY_INTERFACE starts with
  +'CGI-Perl' and if the module Apache::DBI has been loaded. In this case
  +every connect request will be forwarded to the Apache::DBI module. This
  +looks if a database handle from a previous connect request is already
  +stored 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. In
  +other words when the script is run again from a child that has already (and
  +is still) connected, the host/username/password is checked against the
  +cache of open connections, and if one is available, uses that one. There is
  +no need to delete the disconnect statements from your code. They won't do
  +anything because the Apache::DBI module overloads the disconnect method
  +with a NOP (like an empty call).
  +
  +<P>
  +You want to use this module if you are opening a <STRONG>few</STRONG> DB connections to the server. <CODE>Apache::DBI</CODE> will make them persistent per child, so if you have 10 children and each
  +opens 2 different connections you will have in total 20 opened persistent
  +connections. Thus after initial connect you will save up the connection
  +time for every connect request from your DBI module. Which is a huge
  +benefit for the mod_perl apache server with high traffic of users deploying
  +the relational DB.
  +
  +<P>
  +As you understand you must NOT use this module if you are opening a special
  +connection for each of your users, since each of them will stay persistent
  +and in a short time the number of connections will be so big that your
  +machine will scream and die. If you want to use
  +<CODE>Apache::DBI</CODE> in both situations, as of this moment the only available solution is to run
  +2 mod_perl servers, one using
  +<CODE>Apache::DBI</CODE> and one not.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Configuration">Configuration</A></H2></CENTER>
  +<P>
  +After installing this module, the configuration is simple - add to the
  +<CODE>httpd.conf</CODE> the following directive.
  +
  +<P>
  +<PRE>  PerlModule Apache::DBI
  +</PRE>
  +<P>
  +Note that it is important, to load this module before any other ApacheDBI
  +module !
  +
  +<P>
  +You can skip preloading <CODE>DBI</CODE>, since <CODE>Apache::DBI</CODE> does that. But there is no harm if you leave it in.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Preopening_DBI_connections">Preopening DBI connections</A></H2></CENTER>
  +<P>
  +If you want that when you call the script after server restart, the
  +connection will be already preopened, you should use
  +<CODE>connect_on_init()</CODE> method in the startup file to preload every connection you are going to
  +use. For example:
  +
  +<P>
  +<PRE>  Apache::DBI-&gt;connect_on_init
  +  (&quot;DBI:mysql:myDB::myserver&quot;,
  +   &quot;username&quot;,
  +   &quot;passwd&quot;,
  +   {
  +    PrintError =&gt; 1, # warn() on errors
  +    RaiseError =&gt; 0, # don't die on error
  +    AutoCommit =&gt; 1, # commit executes immediately
  +   }
  +  );
  +</PRE>
  +<P>
  +As noted before, it is wise to you this method only if you only want all of
  +apache to be able to connect to the database server as one user (or few
  +users).
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Debugging_Apache_DBI">Debugging Apache::DBI</A></H2></CENTER>
  +<P>
  +If you are not sure this module is working as advertised, you should enable
  +the Debug mode in the startup script by:
  +
  +<P>
  +<PRE>  $Apache::DBI::DEBUG = 1;
  +</PRE>
  +<P>
  +Since now on you will see in the <CODE>error.log</CODE> file when Apache::DBI initializes a connection and when it just returns it
  +from its cache. Use the following command to see it in the real time (your
  +<CODE>error.log</CODE> file might be locate at a different path):
  +
  +<P>
  +<PRE>  tail -f /usr/local/apache/logs/error_log
  +</PRE>
  +<P>
  +I use <CODE>alias</CODE> (in <CODE>tcsh</CODE>) so I will not have to remember the path:
  +
  +<P>
  +<PRE>  alias err &quot;tail -f /usr/local/apache/logs/error_log&quot;
  +</PRE>
  +<P>
  +Another approach is to add to <CODE>httpd.conf</CODE> (which does the same):
  +
  +<P>
  +<PRE>  PerlModule Apache::DebugDBI
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Problems_and_solutions">Problems and solutions</A></H2></CENTER>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="The_morning_bug">The morning bug</A></H3></CENTER>
  +<P>
  +SQL server keeps the connection to the client open for a limited period of
  +time. So many developers were bitten by so called <STRONG>Morning
  +bug</STRONG> when every morning the first users to use the site were receiving:
  +<CODE>No Data Returned</CODE> message, but then everything worked as usual. The error caused by <CODE>Apache::DBI</CODE> returning a handle of the invalid connection (server closed it because of
  +timeout), and the script was dying on that error. The infamous and well
  +documented in the man page,
  +<CODE>ping()</CODE> method was introduced to solve this problem. But seems that people are
  +still being beaten by this problem. Another solution was found - to rise
  +the timeout parameter at the SQL server startup. Currently I startup <CODE>mySQL</CODE> server with <CODE>safe_mysql</CODE>
  +script, so I have updated it to use this option:
  +
  +<P>
  +<PRE>  nohup $ledir/mysqld [snipped other options] -O wait_timeout=172800
  +</PRE>
  +<P>
  +Where 172800 secs equal to 48 hours. And it works.
  +
  +<P>
  +Note that starting from ver. <CODE>0.82</CODE>, <CODE>Apache::DBI</CODE> implements ping inside the <CODE>eval</CODE> block, so if the handle has been timouted, it should reconnect without
  +creating the morning bug.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Opening_a_connection_with_differ">Opening a connection with different parameters</A></H3></CENTER>
  +<P>
  +Q: Currently I am running into a problem where I found out that
  +<CODE>Apache::DBI</CODE> insists that the connection will opened exactly the same way before it will
  +decide to use a cached connection. I.e. if I have one script that sets <CODE>LongReadLen</CODE> and one that does not, it will be two different connections. Instead of
  +having a max of 40 open connections, I end up with 80.
  +
  +<P>
  +A: indeed, <CODE>Apache::DBI</CODE> returns a cached database handle, if and only if all parameters including
  +all options are identical. But you are free to modify the handle right
  +after you got it from the cache. Initiate the connections always using the
  +same parameters and set <CODE>LongReadLen</CODE> afterwards.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Cannot_find_the_DBI_handler">Cannot find the DBI handler</A></H3></CENTER>
  +<P>
  +Q: I cannot find the handler name with which to manipulate my connection;
  +hence I seem to be unable to do anything to my database.
  +
  +<P>
  +A: You did not use <CODE>DBI::connect()</CODE> as with usual DBI usage to get your <CODE>$dbh</CODE> database handler.
  +Using the <CODE>Apache::DBI</CODE> does not eliminate the need to write a proper <CODE>DBI</CODE> code. As the man page states - you should program as if you did not use <CODE>Apache::DBI</CODE> at all. <CODE>Apache::DBI</CODE> will override and return you a cached connection. And in case of <CODE>disconnect()</CODE> call it will be just ignored.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Apache_DBI_does_not_work">Apache:DBI does not work</A></H3></CENTER>
  +<P>
  +Make sure you have it installed.
  +
  +<P>
  +Make sure you configured mod_perl with EVERYTHING=1.
  +
  +<P>
  +Use the example script eg/startup.pl (remove the comment from the line
  +
  +<P>
  +<PRE>  #use Apache::DebugDBI;
  +</PRE>
  +<P>
  +and adapt the connect string. Do not change anything in your scripts, for
  +using Apache::DBI.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="mysql_use_result_vs_mysql_store">mysql_use_result vs. mysql_store_result.</A></H1></CENTER>
  +<P>
  +Since many mod_perl developers uses mysql as their preferable engine, these
  +notes explain the difference between <CODE>mysql_use_result()</CODE> and
  +<CODE>mysql_store_result()</CODE>. The two influence the speed/size of the processes. <CODE>DBD::mysql</CODE> documentation includes the following (version 2.0217) snippet:
  +
  +<P>
  +<PRE>  mysql_use_result attribute: This forces the driver to use
  +  mysql_use_result rather than mysql_store_result. The former is
  +  faster and less memory consuming, but tends to block other
  +  processes. (That's why mysql_store_result is the default.)
  +</PRE>
  +<P>
  +Think about it in client/server terms. When you ask the server to
  +spoon-feed you the data as you use it, the server process must now buffer
  +the data and tie up that thread and possibly keep any database locks open
  +for a much longer time. So if you read a row of data, and ponder it for a
  +while, the tables you have locked are still locked, and the server is busy
  +talking to you every so often. That is
  +<CODE>mysql_use_result()</CODE>.
  +
  +<P>
  +If you just suck down the whole dataset to the client, then the server is
  +free to go about its business serving other requests. This results in
  +parallelism since the server and client are doing work at the same time,
  +rather than blocking on each other doing frequent I/O. That is
  +<CODE>mysql_store_result()</CODE>.
  +
  +<P>
  +As mysql manual suggests: you should not use <CODE>mysql_use_result()</CODE> if you are doing a lot of processing for each row on the client side. This
  +will tie up the server and prevent other threads from updating any tables
  +from which the data are fetched.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A></H1></CENTER>
  +<P>
  +In this section you will find scripts, modules and code snippets to help
  +get yourself started to use relational Databases with mod_perl scripts.
  +Note that I work with <CODE>mysql</CODE> ( <A HREF="http://www.mysql.com">http://www.mysql.com</A> ), so the code
  +you will find will work out of box with mysql, if you use some other SQL
  +engine, it might work for you as well, or some changes should be applied.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A></H2></CENTER>
  +<P>
  +Having to write many queries in my CGI scripts, made me to write a stand
  +alone module that saves me a lot of time in writing and debugging my code.
  +It also makes my scripts are much smaller and easier to read. I will
  +present the module here, afterwards examples will follow:
  +
  +<P>
  +Notice the <CODE>DESTROY</CODE> block at the end of the module, which makes various cleanups and allows
  +this module to be used under <CODE>mod_cgi</CODE> as well.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="My_DB_module">My::DB module</A></H2></CENTER>
  +<P>
  +(note that you will not find it on CPAN)
  +
  +<P>
  +<PRE>  package My::DB;
  +  
  +  use strict;
  +  use 5.004;
  +  
  +  use DBI;
  +  
  +  use vars qw(%c);
  +  
  +  %c =
  +    (
  +       # DB debug
  +     #db_debug   =&gt; 1,
  +     db_debug  =&gt; 0,
  +  
  +     db =&gt; {
  +          DB_NAME      =&gt; 'foo',
  +          SERVER       =&gt; 'localhost',
  +          USER         =&gt; 'put_username_here',
  +          USER_PASSWD  =&gt; 'put_passwd_here',
  +         },
  +  
  +    );
  +  
  +  use Carp qw(croak verbose);
  +  #local $SIG{__WARN__} = \&amp;Carp::cluck;
  +  
  +  # untaint the path by explicit setting
  +  local $ENV{PATH} = '/bin:/usr/bin';
  +  
  +  #######
  +  sub new {
  +    my $proto = shift;
  +    my $class = ref($proto) || $proto;
  +    my $self  = {};
  +  
  +      # connect to the DB, Apache::DBI worries to cache the connections
  +      # save into a dbh - Database handle object
  +    $self-&gt;{dbh} = DBI-&gt;connect(&quot;DBI:mysql:$c{db}{DB_NAME}::$c{db}{SERVER}&quot;,
  +                               $c{db}{USER},
  +                               $c{db}{USER_PASSWD},
  +                               {
  +                                PrintError =&gt; 1, # warn() on errors
  +                                RaiseError =&gt; 0, # don't die on error
  +                                AutoCommit =&gt; 1, # commit executes immediately
  +                               }
  +                              )
  +      or DBI-&gt;disconnect(&quot;Cannot connect to database: $DBI::errstr\n&quot;);
  +  
  +      # we want to die on errors if in debug mode
  +    $self-&gt;{dbh}-&gt;{RaiseError} = 1 if $c{'db_debug'};
  +  
  +      # init the sth - Statement handle object
  +    $self-&gt;{sth} = '';
  +  
  +    bless ($self, $class);
  +  
  +    $self;
     
  +  } # end of sub new
  +  
     
     
     ######################################################################
  -  # return a ref to hash of single matched row, by conditions
  -  # and restrictions. return undef if nothing matched.
  -  # (column1 =&gt; value1, column2 =&gt; value2) or empty () if non matched
  -  #
  -  # sql_get_hash_ref($table_name,\@columns,\@conditions,\@restrictions);
  +                 ###################################
  +                 ###                             ###
  +                 ###       SQL Functions         ###
  +                 ###                             ###
  +                 ###################################
  +  ######################################################################
  +  
  +  # print debug messages
  +  sub d{
  +     # we want to print in debug mode the trace
  +    print &quot;&lt;DT&gt;&lt;B&gt;&quot;.join(&quot;&lt;BR&gt;&quot;, @_).&quot;&lt;/B&gt;\n&quot; if $c{'db_debug'};
  +  
  +  } # end of sub d
  +  
  +  
  +  ######################################################################
  +  # return a count of matched rows, by conditions 
     #
  -  # columns is a list of columns to be returned (username, fname,...)
  +  #  $count = sql_count_matched($table_name,\@conditions);
     #
     # conditions must be an array so we can path more than one column with
     # the same name.
  +  #
     #  @conditions =  ( column =&gt; ['comp_sign','value'],
     #                  foo    =&gt; ['&gt;',15],
     #                  foo    =&gt; ['&lt;',30],
     #                );
  -  # The sub knows automatically to detect and quote strings
     #
  -  # restrictions is a list of restrictions like ('order by email')
  +  # The sub knows automatically to detect and quote strings
     #
     ##########################
  -  sub sql_get_hash_ref{
  +  sub sql_count_matched{
       my $self    = shift;
       my $table   = shift || '';
  -    my $r_cols  = shift || [];
       my $r_conds = shift || [];
  -    my $r_restr = shift || [];
     
         # we want to print in debug mode the trace
       d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
     
         # build the query
  -    my $do_sql = &quot;SELECT &quot;;
  -    $do_sql .= join &quot;,&quot;, @{$r_cols} if @{$r_cols};
  -    $do_sql .= &quot; FROM $table &quot;;
  -  
  +    my $do_sql = &quot;SELECT COUNT(*) FROM $table &quot;;
       my @where = ();
       for(my $i=0;$i&lt;@{$r_conds};$i=$i+2) {
         push @where, join &quot; &quot;,
  @@ -10297,65 +10940,48 @@
           sql_quote(sql_escape($$r_conds[$i+1][1]));
       }
         # Add the where clause if we have one
  -    $do_sql .= &quot; WHERE &quot;. join &quot; AND &quot;, @where if @where;
  -  
  -      # restrictions (DONT put commas!)
  -    $do_sql .= &quot; &quot;. join &quot; &quot;, @{$r_restr} if @{$r_restr};
  +    $do_sql .= &quot;WHERE &quot;. join &quot; AND &quot;, @where if @where;
     
       d(&quot;SQL: $do_sql&quot;);
     
         # do query
       $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
       $self-&gt;{sth}-&gt;execute();
  +    my ($count) = $self-&gt;{sth}-&gt;fetchrow_array;
     
  -    return $self-&gt;{sth}-&gt;fetchrow_hashref;
  +    d(&quot;Result: $count&quot;);
     
  -  } # end of sub sql_get_hash_ref
  +    $self-&gt;{sth}-&gt;finish;
     
  +    return $count;
     
  +  } # end of sub sql_count_matched
     
     
     
     ######################################################################
  -  # returns a reference to an array, matched by conditions and
  -  # restrictions, which contains one reference to array per row. If
  -  # there are no rows to return, returns a reference to an empty array:
  -  # [
  -  #  [array1],
  -  #   ......
  -  #  [arrayN],
  -  # ];
  +  # return a single (first) matched value or undef, by conditions and
  +  # restrictions
     #
  -  # $ref = sql_get_matched_rows_ary_ref($table_name,\@columns,\@conditions,\@restrictions);
  +  # sql_get_matched_value($table_name,$column,\@conditions,\@restrictions);
     #
  -  # columns is a list of columns to be returned (username, fname,...)
  +  # column is a name of the column
     #
     # conditions must be an array so we can path more than one column with
  -  # the same name. @conditions are being cancatenated with AND
  +  # the same name.
     #  @conditions =  ( column =&gt; ['comp_sign','value'],
     #                  foo    =&gt; ['&gt;',15],
     #                  foo    =&gt; ['&lt;',30],
     #                );
  -  # results in
  -  # WHERE foo &gt; 15 AND foo &lt; 30
  -  #
  -  #  to make an OR logic use (then ANDed )
  -  #  @conditions =  ( column =&gt; ['comp_sign',['value1','value2']],
  -  #                  foo    =&gt; ['=',[15,24] ],
  -  #                  bar    =&gt; ['=',[16,21] ],
  -  #                );
  -  # results in
  -  # WHERE (foo = 15 OR foo = 24) AND (bar = 16 OR bar = 21)
  -  #
     # The sub knows automatically to detect and quote strings
     #
     # restrictions is a list of restrictions like ('order by email')
     #
     ##########################
  -  sub sql_get_matched_rows_ary_ref{
  +  sub sql_get_matched_value{
       my $self    = shift;
       my $table   = shift || '';
  -    my $r_cols  = shift || [];
  +    my $column  = shift || '';
       my $r_conds = shift || [];
       my $r_restr = shift || [];
     
  @@ -10363,30 +10989,15 @@
       d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
     
         # build the query
  -    my $do_sql = &quot;SELECT &quot;;
  -    $do_sql .= join &quot;,&quot;, @{$r_cols} if @{$r_cols};
  -    $do_sql .= &quot; FROM $table &quot;;
  +    my $do_sql = &quot;SELECT $column FROM $table &quot;;
     
       my @where = ();
       for(my $i=0;$i&lt;@{$r_conds};$i=$i+2) {
  -  
  -      if (ref $$r_conds[$i+1][1] eq 'ARRAY') {
  -          # multi condition for the same field/comparator to be ORed
  -        push @where, map {&quot;($_)&quot;} join &quot; OR &quot;,
  -        map { join &quot; &quot;, 
  -                $r_conds-&gt;[$i],
  -                $r_conds-&gt;[$i+1][0],
  -                sql_quote(sql_escape($_));
  -            } @{$r_conds-&gt;[$i+1][1]};
  -      } else {
  -          # single condition for the same field/comparator
  -        push @where, join &quot; &quot;,
  -        $r_conds-&gt;[$i],
  -          $r_conds-&gt;[$i+1][0],
  -          sql_quote(sql_escape($r_conds-&gt;[$i+1][1]));
  -      }
  -    } # end of for(my $i=0;$i&lt;@{$r_conds};$i=$i+2
  -  
  +      push @where, join &quot; &quot;,
  +        $$r_conds[$i],
  +        $$r_conds[$i+1][0],
  +        sql_quote(sql_escape($$r_conds[$i+1][1]));
  +    }
         # Add the where clause if we have one
       $do_sql .= &quot; WHERE &quot;. join &quot; AND &quot;, @where if @where;
     
  @@ -10396,87 +11007,48 @@
       d(&quot;SQL: $do_sql&quot;);
     
         # do query
  -    return $self-&gt;{dbh}-&gt;selectall_arrayref($do_sql);
  -  
  -  } # end of sub sql_get_matched_rows_ary_ref
  -  
  -  
  -  
  -  
  -  ######################################################################
  -  # insert a single row into a DB
  -  #
  -  #  sql_insert_row($table_name,\%data,$delayed);
  -  #
  -  # data is hash of type (column1 =&gt; value1 ,column2 =&gt; value2 , )
  -  #
  -  # $delayed: 1 =&gt; do delayed insert, 0 or none passed =&gt; immediate
  -  #
  -  # * The sub knows automatically to detect and quote strings 
  -  #
  -  # * The insert id delayed, so the user will not wait untill the insert
  -  # will be completed, if many select queries are running 
  -  #
  -  ##########################
  -  sub sql_insert_row{
  -    my $self    = shift;
  -    my $table   = shift || '';
  -    my $r_data = shift || {};
  -    my $delayed = (shift) ? 'DELAYED' : '';
  -  
  -      # we want to print in debug mode the trace
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
  -  
  -      # build the query
  -    my $do_sql = &quot;INSERT $delayed INTO $table &quot;;
  -    $do_sql   .= &quot;(&quot;.join(&quot;,&quot;,keys %{$r_data}).&quot;)&quot;;
  -    $do_sql   .= &quot; VALUES (&quot;;
  -    $do_sql   .= join &quot;,&quot;, sql_quote(sql_escape( values %{$r_data} ) );
  -    $do_sql   .= &quot;)&quot;;
  +    return $self-&gt;{dbh}-&gt;selectrow_array($do_sql);
     
  -    d(&quot;SQL: $do_sql&quot;);
  +  } # end of sub sql_get_matched_value
     
  -      # do query
  -    $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
  -    $self-&gt;{sth}-&gt;execute();
     
  -  } # end of sub sql_insert_row
     
     
     ######################################################################
  -  # update rows in a DB by condition
  +  # return a single row of first matched rows, by conditions and
  +  # restrictions. The row is being inserted into @results_row array
  +  # (value1,value2,...)  or empty () if non matched
     #
  -  #  sql_update_rows($table_name,\%data,\@conditions,$delayed);
  +  # sql_get_matched_row(\@results_row,$table_name,\@columns,\@conditions,\@restrictions);
     #
  -  # data is hash of type (column1 =&gt; value1 ,column2 =&gt; value2 , )
  +  # columns is a list of columns to be returned (username, fname,...)
     #
     # conditions must be an array so we can path more than one column with
     # the same name.
     #  @conditions =  ( column =&gt; ['comp_sign','value'],
  -  #                  foo    =&gt; ['&gt;',15],
  -  #                  foo    =&gt; ['&lt;',30],
  -  #                ); 
  -  #
  -  # $delayed: 1 =&gt; do delayed insert, 0 or none passed =&gt; immediate
  -  #
  -  # * The sub knows automatically to detect and quote strings 
  +  #                  foo    =&gt; ['&gt;',15],
  +  #                  foo    =&gt; ['&lt;',30],
  +  #                );
  +  # The sub knows automatically to detect and quote strings
     #
  +  # restrictions is a list of restrictions like ('order by email')
     #
     ##########################
  -  sub sql_update_rows{
  +  sub sql_get_matched_row{
       my $self    = shift;
  +    my $r_row   = shift || {};
       my $table   = shift || '';
  -    my $r_data = shift || {};
  +    my $r_cols  = shift || [];
       my $r_conds = shift || [];
  -    my $delayed = (shift) ? 'LOW_PRIORITY' : '';
  +    my $r_restr = shift || [];
     
         # we want to print in debug mode the trace
       d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
     
         # build the query
  -    my $do_sql = &quot;UPDATE $delayed $table SET &quot;;
  -    $do_sql   .= join &quot;,&quot;, 
  -      map { &quot;$_=&quot;.join &quot;&quot;,sql_quote(sql_escape($$r_data{$_})) } keys %{$r_data};
  +    my $do_sql = &quot;SELECT &quot;;
  +    $do_sql .= join &quot;,&quot;, @{$r_cols} if @{$r_cols};
  +    $do_sql .= &quot; FROM $table &quot;;
     
       my @where = ();
       for(my $i=0;$i&lt;@{$r_conds};$i=$i+2) {
  @@ -10488,25 +11060,26 @@
         # Add the where clause if we have one
       $do_sql .= &quot; WHERE &quot;. join &quot; AND &quot;, @where if @where;
     
  +      # restrictions (DONT put commas!)
  +    $do_sql .= &quot; &quot;. join &quot; &quot;, @{$r_restr} if @{$r_restr};
     
       d(&quot;SQL: $do_sql&quot;);
     
         # do query
  -    $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
  -  
  -    $self-&gt;{sth}-&gt;execute();
  +    @{$r_row} = $self-&gt;{dbh}-&gt;selectrow_array($do_sql);
     
  -  #  my ($count) = $self-&gt;{sth}-&gt;fetchrow_array;
  -  #
  -  #  d(&quot;Result: $count&quot;);
  +  } # end of sub sql_get_matched_row
     
  -  } # end of sub sql_update_rows
     
     
     ######################################################################
  -  # delete rows from DB by condition
  +  # return a ref to hash of single matched row, by conditions
  +  # and restrictions. return undef if nothing matched.
  +  # (column1 =&gt; value1, column2 =&gt; value2) or empty () if non matched
     #
  -  # sql_delete_rows($table_name,\@conditions);
  +  # sql_get_hash_ref($table_name,\@columns,\@conditions,\@restrictions);
  +  #
  +  # columns is a list of columns to be returned (username, fname,...)
     #
     # conditions must be an array so we can path more than one column with
     # the same name.
  @@ -10514,21 +11087,25 @@
     #                  foo    =&gt; ['&gt;',15],
     #                  foo    =&gt; ['&lt;',30],
     #                );
  -  #
  -  # * The sub knows automatically to detect and quote strings 
  +  # The sub knows automatically to detect and quote strings
     #
  +  # restrictions is a list of restrictions like ('order by email')
     #
     ##########################
  -  sub sql_delete_rows{
  +  sub sql_get_hash_ref{
       my $self    = shift;
       my $table   = shift || '';
  +    my $r_cols  = shift || [];
       my $r_conds = shift || [];
  +    my $r_restr = shift || [];
     
         # we want to print in debug mode the trace
       d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
     
         # build the query
  -    my $do_sql = &quot;DELETE FROM $table &quot;;
  +    my $do_sql = &quot;SELECT &quot;;
  +    $do_sql .= join &quot;,&quot;, @{$r_cols} if @{$r_cols};
  +    $do_sql .= &quot; FROM $table &quot;;
     
       my @where = ();
       for(my $i=0;$i&lt;@{$r_conds};$i=$i+2) {
  @@ -10537,765 +11114,511 @@
           $$r_conds[$i+1][0],
           sql_quote(sql_escape($$r_conds[$i+1][1]));
       }
  -  
  -      # Must be very carefull with deletes, imagine somehow @where is
  -      # not getting set, &quot;DELETE FROM NAME&quot; deletes the contents of the table
  -    warn(&quot;Attempt to delete a whole table $table from DB\n!!!&quot;),return unless @where;
  -  
         # Add the where clause if we have one
  -    $do_sql .= &quot; WHERE &quot;. join &quot; AND &quot;, @where;
  +    $do_sql .= &quot; WHERE &quot;. join &quot; AND &quot;, @where if @where;
     
  +      # restrictions (DONT put commas!)
  +    $do_sql .= &quot; &quot;. join &quot; &quot;, @{$r_restr} if @{$r_restr};
  +  
       d(&quot;SQL: $do_sql&quot;);
     
         # do query
       $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
       $self-&gt;{sth}-&gt;execute();
  -  
  -  } # end of sub sql_delete_rows
  -  
  -  
  -  ######################################################################
  -  # executes the passed query and returns a reference to an array which
  -  # contains one reference per row. If there are no rows to return,
  -  # returns a reference to an empty array.
  -  #
  -  # $r_array = sql_execute_and_get_r_array($query);
  -  #
  -  #
  -  ##########################
  -  sub sql_execute_and_get_r_array{
  -    my $self     = shift;
  -    my $do_sql   = shift || '';
  -  
  -      # we want to print in debug mode the trace
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
  -  
  -    d(&quot;SQL: $do_sql&quot;);
  -  
  -    $self-&gt;{dbh}-&gt;selectall_arrayref($do_sql);
  -  
  -  } # end of sub sql_execute_and_get_r_array
  -  
  -  
  -  
  -  #
  -  #
  -  # return current date formatted for a DATE field type
  -  # YYYYMMDD
  -  #
  -  ############
  -  sub sql_date{
  -    my $self     = shift;
  -  
  -    my ($sec,$min,$hour,$mday,$mon,$year) = localtime();
  -    $year = ($year&gt;70) ? sprintf &quot;19%0.2d&quot;,$year : sprintf &quot;20%0.2d&quot;,$year;
  -    return sprintf &quot;%0.4d%0.2d%0.2d&quot;,$year,++$mon,$mday;
  -  
  -  } # end of sub sql_date
  -  
  -  #
  -  #
  -  # return current date formatted for a DATE field type
  -  # YYYYMMDDHHMMSS
  -  #
  -  ############
  -  sub sql_datetime{
  -    my $self     = shift;
  -  
  -    my ($sec,$min,$hour,$mday,$mon,$year) = localtime();
  -    $year = ($year&gt;70) ? sprintf &quot;19%0.2d&quot;,$year : sprintf &quot;20%0.2d&quot;,$year;
  -    return sprintf &quot;%0.4d%0.2d%0.2d%0.2d%0.2d%0.2d&quot;,$year,++$mon,$mday,$hour,$min,$sec;
  -  
  -  } # end of sub sql_datetime
  -  
  -  
  -  # 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; } @_ }
  -  
  -  # 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 }
     
  -  
  -  # DESTROY makes all kinds of cleanups if the fuctions were interuppted
  -  # before their completion and haven't had a chance to make a clean up.
  -  ###########
  -  sub DESTROY{
  -    my $self = shift;
  -  
  -    $self-&gt;{sth}-&gt;finish     if defined $self-&gt;{sth} and $self-&gt;{sth};
  -    $self-&gt;{dbh}-&gt;disconnect if defined $self-&gt;{dbh} and $self-&gt;{dbh};
  -  
  -  } # end of sub DESTROY
  -  
  -  
  -  
  -  # Don't remove
  -  1;
  -</PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A></H3></CENTER>
  -<P>
  -In your code that wants to use <CODE>My::DB</CODE>, you have to create a
  -<CODE>My::DB</CODE> object first:
  -
  -<P>
  -<PRE>  use vars qw($db_obj);
  -  my $db_obj = new My::DB or croak &quot;Can't initialize My::DB object: $!\n&quot;;
  -</PRE>
  -<P>
  -From this moment, you can use any <CODE>My::DB</CODE>'s methods. I will start from a very simple query - I want to know where
  -the users are and produce statistics. <CODE>tracker</CODE> is the name of the table.
  -
  -<P>
  -<PRE>    # fetch the statistics of where users are
  -  my $r_ary = $db_obj-&gt;sql_get_matched_rows_ary_ref
  -    (&quot;tracker&quot;,
  -     [qw(where_user_are)],
  -    );
  +    return $self-&gt;{sth}-&gt;fetchrow_hashref;
     
  -  my %stats = ();
  -  my $total = 0;
  -  foreach my $r_row (@$r_ary){
  -    $stats{$r_row-&gt;[0]}++;
  -    $total++;
  -  }
  -</PRE>
  -<P>
  -Now let's count how many users do we have (in <CODE>users</CODE> table):
  -
  -<P>
  -<PRE>  my $count = $db_obj-&gt;sql_count_matched(&quot;users&quot;);
  -</PRE>
  -<P>
  -Check whether user exists:
  -
  -<P>
  -<PRE>  my $username = 'stas';
  -  my $exists = $db_obj-&gt;sql_count_matched
  -  (&quot;users&quot;,
  -   [username =&gt; [&quot;=&quot;,$username]]
  -  );
  -</PRE>
  -<P>
  -Check whether user online and get time since when she is online (<CODE>since</CODE> a column in the <CODE>tracker</CODE> table telling since when user is online):
  -
  -<P>
  -<PRE>  my @row = ();
  -  $db_obj-&gt;sql_get_matched_row
  -  (\@row,
  -   &quot;tracker&quot;,
  -   ['UNIX_TIMESTAMP(since)'],
  -   [username =&gt; [&quot;=&quot;,$username]]
  -  );
  +  } # end of sub sql_get_hash_ref
     
  -  if (@row) {
  -    my $idle = int( (time() - $row[0]) / 60);
  -    return &quot;Current status: Is Online and idle for $idle minutes.&quot;;
  -  }
  -</PRE>
  -<P>
  -A complex query. I do join of 2 tables, and want to get a reference to
  -array, which will store a slice of the matched query (<CODE>LIMIT
  -$offset,$hits</CODE>), sorted by <CODE>username</CODE> and each row in array_ref to include the fields from the <CODE>users</CODE> table, but only those listed in
  -<CODE>@verbose_cols</CODE>. Then we print it out.
  -
  -<P>
  -<PRE>  my $r_ary = $db_obj-&gt;sql_get_matched_rows_ary_ref
  -    (
  -     &quot;tracker STRAIGHT_JOIN users&quot;,
  -     [map {&quot;users.$_&quot;} @verbose_cols],
  -     [],
  -     [&quot;WHERE tracker.username=users.username&quot;,
  -      &quot;ORDER BY users.username&quot;,
  -      &quot;LIMIT $offset,$hits&quot;],
  -    );
     
  -  foreach my $r_row (@$r_ary){
  -    print ...
  -  }
  -</PRE>
  -<P>
  -Another complex query. User checks checkboxes to be queried by, selects
  -from lists and types in match strings, we process input and build the <CODE>@where</CODE> array. Then we want to get the number of matches and the matched rows as
  -well.
  -
  -<P>
  -<PRE>  my @where = ();
  -    # process chekoxes - we turn them into REGEXP
  -  foreach (keys %search_keys) {
  -    next unless defined $q-&gt;param($_) and $q-&gt;param($_);
  -    my $regexp = &quot;[&quot;.join(&quot;&quot;,$q-&gt;param($_)).&quot;]&quot;;
  -    push @where, ($_ =&gt; ['REGEXP',$regexp]);
  -  }
     
  -    # Now add all the single answer , selected =&gt; exact macth
  -  push @where,(country =&gt; ['=',$q-&gt;param('country')]) if $q-&gt;param('country');
     
  -    # Now add all the typed params
  -  foreach (qw(city state)) {
  -    push @where,($_ =&gt; ['LIKE',$q-&gt;param($_)]) if $q-&gt;param($_);
  -  }
     
  -     # Do the count all matched query
  -  my $total_matched_users =  $db_obj-&gt;sql_count_matched
  -    (
  -     &quot;users&quot;,
  -     \@where,
  -    );
  +  ######################################################################
  +  # returns a reference to an array, matched by conditions and
  +  # restrictions, which contains one reference to array per row. If
  +  # there are no rows to return, returns a reference to an empty array:
  +  # [
  +  #  [array1],
  +  #   ......
  +  #  [arrayN],
  +  # ];
  +  #
  +  # $ref = sql_get_matched_rows_ary_ref($table_name,\@columns,\@conditions,\@restrictions);
  +  #
  +  # columns is a list of columns to be returned (username, fname,...)
  +  #
  +  # conditions must be an array so we can path more than one column with
  +  # the same name. @conditions are being cancatenated with AND
  +  #  @conditions =  ( column =&gt; ['comp_sign','value'],
  +  #                  foo    =&gt; ['&gt;',15],
  +  #                  foo    =&gt; ['&lt;',30],
  +  #                );
  +  # results in
  +  # WHERE foo &gt; 15 AND foo &lt; 30
  +  #
  +  #  to make an OR logic use (then ANDed )
  +  #  @conditions =  ( column =&gt; ['comp_sign',['value1','value2']],
  +  #                  foo    =&gt; ['=',[15,24] ],
  +  #                  bar    =&gt; ['=',[16,21] ],
  +  #                );
  +  # results in
  +  # WHERE (foo = 15 OR foo = 24) AND (bar = 16 OR bar = 21)
  +  #
  +  # The sub knows automatically to detect and quote strings
  +  #
  +  # restrictions is a list of restrictions like ('order by email')
  +  #
  +  ##########################
  +  sub sql_get_matched_rows_ary_ref{
  +    my $self    = shift;
  +    my $table   = shift || '';
  +    my $r_cols  = shift || [];
  +    my $r_conds = shift || [];
  +    my $r_restr = shift || [];
     
  -    # Now process the orderby
  -  my $orderby = $q-&gt;param('orderby') || 'username';
  +      # we want to print in debug mode the trace
  +    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
     
  -     # Do the query and fetch the data
  -  my $r_ary = $db_obj-&gt;sql_get_matched_rows_ary_ref
  -  (
  -   &quot;users&quot;,
  -   \@display_columns,
  -   \@where,
  -   [&quot;ORDER BY $orderby&quot;,
  -    &quot;LIMIT $offset,$hits&quot;],
  -  );
  -</PRE>
  -<P>
  -<CODE>sql_get_matched_rows_ary_ref</CODE> knows to handle both <CODE>OR</CODE>ed and
  -<CODE>AND</CODE>ed params. This example shows how to use <CODE>OR</CODE> on parameters:
  -
  -<P>
  -This snippet is an implementation of the watchdog. Users register usernames
  -of the people they want to know when these are going online, so we have to
  -make 2 queries - one to get a list of these usernames, second to query
  -whether any of these users is online. In the second query we use <CODE>OR</CODE> keyword.
  -
  -<P>
  -<PRE>  # check who we are looking for
  -  $r_ary = $db_obj-&gt;sql_get_matched_rows_ary_ref
  -    (&quot;watchdog&quot;,
  -     [qw(watched)],
  -     [username =&gt; ['=',$username)],
  -     ],
  -    );
  +      # build the query
  +    my $do_sql = &quot;SELECT &quot;;
  +    $do_sql .= join &quot;,&quot;, @{$r_cols} if @{$r_cols};
  +    $do_sql .= &quot; FROM $table &quot;;
     
  -    # put them into an array
  -  my @watched = map {$_-&gt;[0]} @{$r_ary};
  +    my @where = ();
  +    for(my $i=0;$i&lt;@{$r_conds};$i=$i+2) {
     
  -  my %matched = ();
  -    # Do user has some registered usernames?
  -  if (@watched) {
  +      if (ref $$r_conds[$i+1][1] eq 'ARRAY') {
  +          # multi condition for the same field/comparator to be ORed
  +        push @where, map {&quot;($_)&quot;} join &quot; OR &quot;,
  +        map { join &quot; &quot;, 
  +                $r_conds-&gt;[$i],
  +                $r_conds-&gt;[$i+1][0],
  +                sql_quote(sql_escape($_));
  +            } @{$r_conds-&gt;[$i+1][1]};
  +      } else {
  +          # single condition for the same field/comparator
  +        push @where, join &quot; &quot;,
  +        $r_conds-&gt;[$i],
  +          $r_conds-&gt;[$i+1][0],
  +          sql_quote(sql_escape($r_conds-&gt;[$i+1][1]));
  +      }
  +    } # end of for(my $i=0;$i&lt;@{$r_conds};$i=$i+2
     
  -  # try to bring all the users who match (exactly) the usernames - put
  -  # it into array and compare with a hash!
  -    $r_ary = $db_obj-&gt;sql_get_matched_rows_ary_ref
  -      (&quot;tracker&quot;,
  -       [qw(username)],
  -       [username =&gt; ['=',\@watched],
  -       ]
  -      );
  +      # Add the where clause if we have one
  +    $do_sql .= &quot; WHERE &quot;. join &quot; AND &quot;, @where if @where;
     
  -    map {$matched{$_-&gt;[0]} = 1} @{$r_ary};
  -  }
  +      # restrictions (DONT put commas!)
  +    $do_sql .= &quot; &quot;. join &quot; &quot;, @{$r_restr} if @{$r_restr};
     
  -  # Now %matched includes the usernames of the users who are being
  -  # watched by $username and currently are online.
  -</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>.
  -
  -	     <HR>
  -	     [    <A HREF="security.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="dbm.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: mod_perl and dbm files</TITLE>
  -   <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
  -   <META NAME="Author" CONTENT="Bekman Stas">
  -   <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>
  -mod_perl and dbm files</H1>
  -<HR WIDTH="100%">
  -	    [    <A HREF="databases.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="multiuser.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  -<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  -<UL>
  -
  -	<LI><A HREF="#Where_and_Why_to_use_dbm_files">Where and Why to use dbm files</A>
  -	<LI><A HREF="#mod_perl_and_dbm">mod_perl and dbm</A>
  -	<LI><A HREF="#Locking_dbm_handlers">Locking dbm handlers</A>
  -	<LI><A HREF="#Tie_DB_Lock">Tie::DB_Lock</A>
  -	<LI><A HREF="#Code_snippets">Code snippets</A>
  -</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="Where_and_Why_to_use_dbm_files">Where and Why to use dbm files</A></H1></CENTER>
  -<P>
  -dbm files are the first implementations of the databases, which originated
  -on Unix systems, and currently being used in many Unix applications where
  -simple key-value pairs should be stored and manipulated. As of this writing
  -Berkeley DB is the most powerful dbm implementation. If you need a light
  -database, with easy API to work with this is a solution that should be
  -considered as a first one. Of course only if you are sure the DB you are
  -going to use will stay small, I would say under 5000-10000 records, but it
  -depends on your hardware, which can rise and lower the numbers above. It is
  -a much better solution over the flat file databases which become pretty
  -slow on insert, update and delete operations when the number of records
  -grows beyond 1000. The situation is even worse when we need to run sort on
  -this kind of DB.
  -
  -<P>
  -dbm files are being manipulated much faster than their flat file brothers,
  -since almost never the whole DB is being read into a memory and because of
  -smart storage technique. You can use a <CODE>HASH</CODE>
  -algorithm which allows a <CODE>0(1)</CODE> complexity of search and update, fast insert and delete, but slow sort,
  -since you have to do it yourself. <CODE>BTREE</CODE> allows arbitrary key/value pairs to be stored in a sorted, balanced binary
  -tree, which allows us to get a sorted sequence of data pairs in <CODE>0(1)</CODE>, but much slower insert, update, delete operations. <CODE>RECNO</CODE> algorithm is more complicated one, and enables for both fixed-length and
  -variable-length flat text files to be manipulated using the same key/value
  -pair interface as in <CODE>HASH</CODE> and
  -<CODE>BTREE</CODE>. In this case the key will consist of a record (line) number. Most chances
  -you will want to use the <CODE>HASH</CODE> format, but your choice is very dependent on a kind of your application.
  -
  -<P>
  -<STRONG>dbm</STRONG> databases are not limited for key and value pairs storages, but can store
  -more complicated structures with help of <CODE>MLDBM</CODE>
  -module. Which can dump and restore the whole symbol table of your script,
  -including arrays, hashes and other complicated data <CODE>HASH</CODE>
  -structures.
  -
  -<P>
  -Another important thing to say, is that you cannot convert a dbm file from
  -one storing algorithm to another, by simply tying it using a wanted format.
  -The only way is to dump it into a flat file and then restore it using a new
  -format. You can use a script like:
  -
  -<P>
  -<PRE>  #!/usr/bin/perl -w
  +    d(&quot;SQL: $do_sql&quot;);
     
  +      # do query
  +    return $self-&gt;{dbh}-&gt;selectall_arrayref($do_sql);
  +  
  +  } # end of sub sql_get_matched_rows_ary_ref
  +  
  +  
  +  
  +  
  +  ######################################################################
  +  # insert a single row into a DB
     #
  -  # This script gets as a parameter a Berkeley DB file(s) which is stored
  -  # with DB_BTREE algorithm, and will backup it with .bak and create
  -  # instead the db with the same records but stored with DB_HASH
  -  # algorithm
  +  #  sql_insert_row($table_name,\%data,$delayed);
     #
  -  # Usage: btree2hash.pl filename(s)
  +  # data is hash of type (column1 =&gt; value1 ,column2 =&gt; value2 , )
  +  #
  +  # $delayed: 1 =&gt; do delayed insert, 0 or none passed =&gt; immediate
  +  #
  +  # * The sub knows automatically to detect and quote strings 
  +  #
  +  # * The insert id delayed, so the user will not wait untill the insert
  +  # will be completed, if many select queries are running 
  +  #
  +  ##########################
  +  sub sql_insert_row{
  +    my $self    = shift;
  +    my $table   = shift || '';
  +    my $r_data = shift || {};
  +    my $delayed = (shift) ? 'DELAYED' : '';
     
  -  use strict;
  -  use DB_File;
  -  use File::Copy;
  +      # we want to print in debug mode the trace
  +    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
     
  -    # Do checks 
  -  die &quot;Usage: btree2hash.pl filename(s))\n&quot; unless @ARGV;
  +      # build the query
  +    my $do_sql = &quot;INSERT $delayed INTO $table &quot;;
  +    $do_sql   .= &quot;(&quot;.join(&quot;,&quot;,keys %{$r_data}).&quot;)&quot;;
  +    $do_sql   .= &quot; VALUES (&quot;;
  +    $do_sql   .= join &quot;,&quot;, sql_quote(sql_escape( values %{$r_data} ) );
  +    $do_sql   .= &quot;)&quot;;
     
  -  foreach my $filename (@ARGV) {
  +    d(&quot;SQL: $do_sql&quot;);
     
  -    die &quot;Can't find $filename: $!\n&quot; unless -e $filename and -r $filename;
  +      # do query
  +    $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
  +    $self-&gt;{sth}-&gt;execute();
     
  -      # First backup the filename
  -    move(&quot;$filename&quot;,&quot;$filename.btree&quot;) 
  -      or die &quot;can't move $filename $filename.btree:$!\n&quot;;
  +  } # end of sub sql_insert_row
     
  -    my %hash;
  -    my %btree;
     
  -      # tie both dbs (db_hash is a fresh one!)
  -    tie %btree , 'DB_File',&quot;$filename.btree&quot;, O_RDWR|O_CREAT, 
  -        0660, $DB_BTREE or die &quot;Can't tie %btree&quot;;
  -    tie %hash ,  'DB_File',&quot;$filename&quot; , O_RDWR|O_CREAT, 
  -        0660, $DB_HASH  or die &quot;Can't tie %hash&quot;;
  +  ######################################################################
  +  # update rows in a DB by condition
  +  #
  +  #  sql_update_rows($table_name,\%data,\@conditions,$delayed);
  +  #
  +  # data is hash of type (column1 =&gt; value1 ,column2 =&gt; value2 , )
  +  #
  +  # conditions must be an array so we can path more than one column with
  +  # the same name.
  +  #  @conditions =  ( column =&gt; ['comp_sign','value'],
  +  #                  foo    =&gt; ['&gt;',15],
  +  #                  foo    =&gt; ['&lt;',30],
  +  #                ); 
  +  #
  +  # $delayed: 1 =&gt; do delayed insert, 0 or none passed =&gt; immediate
  +  #
  +  # * The sub knows automatically to detect and quote strings 
  +  #
  +  #
  +  ##########################
  +  sub sql_update_rows{
  +    my $self    = shift;
  +    my $table   = shift || '';
  +    my $r_data = shift || {};
  +    my $r_conds = shift || [];
  +    my $delayed = (shift) ? 'LOW_PRIORITY' : '';
     
  -      # copy DB
  -    %hash = %btree;
  +      # we want to print in debug mode the trace
  +    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
     
  -      # untie
  -    untie %btree ;
  -    untie %hash ;
  -  }
  -</PRE>
  -<P>
  -Note that some dbm implementations come with other conversion utilities as
  -well.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="mod_perl_and_dbm">mod_perl and dbm</A></H1></CENTER>
  -<P>
  -Where mod_perl enters into a picture? If you are using a read only dbm file
  -you can have it work faster if you keep it open (tied) all the time, so
  -when your CGI script wants to access the database it is already tied and
  -ready to be used. It will work as well with your dynamic dbm databases as
  -well but you need to use locking to avoid data corruptions. Of course this
  -feature can make a huge speedup to your CGIs, but you should be very
  -careful. What should be taken into account is a db locking, handling
  -possible <CODE>die()</CODE> cases and child quits. A stale lock can deactivate your whole site, if your
  -locking mechanism cannot handle dropped locks. You can enter a deadlock
  -situations if 2 processes are trying to acquire locks on 2 databases, but
  -get stuck because each has got hands on one of the 2 databases, and to
  -release it, each process needs the second one, which will never be freed,
  -because that is the condition for the first one to be released (possible
  -only if processes do not all ask for their DB files in the same order). If
  -you modify the DB you should be very careful to flush and synchronize it,
  -especially when your CGI unexpectedly dies. In general your application
  -should be tested very thoroughly before you put it into production to
  -handle important data.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Locking_dbm_handlers">Locking dbm handlers</A></H1></CENTER>
  -<P>
  -Let's have a lock status as a global variable, so it will persist from
  -request to request. If we are requesting a lock - READ (shared) or WRITE
  -(exclusive), the current lock status is being obtained first.
  -
  -<P>
  -If we get a READ lock request, it is granted as soon as file becomes or is
  -locked or already locked for READ. Lock status is READ now.
  -
  -<P>
  -If we get a WRITE lock request, it is granted as soon as file becomes or is
  -unlocked. Lock status is WRITE now.
  -
  -<P>
  -What happens to the WRITE lock request, is the most important. If the DB is
  -being READ locked, request that request to write will poll until there will
  -be no reading or writing process left. Lots of processes can successfully
  -read the file, since they do not block each other from doing so. This means
  -that a process that wants to write to the file (first obtaining an
  -exclusive lock) never gets a chance to squeeze in. The following diagram
  -represents a possible scenario where everybody read but no one can write:
  -
  -<P>
  -<PRE>  [-p1-]                 [--p1--]
  -     [--p2--]
  -   [---------p3---------]
  -                 [------p4-----]
  -     [--p5--]   [----p5----]
  -</PRE>
  -<P>
  -So you get a starving process, which most certainly will timeout the
  -request, and the DB will be not updated.
  -
  -<P>
  -So you have another reason not to cache the dbm handle with dynamic dbm
  -files. But it will work perfect with the static DBM files without a need to
  -lock files at all. Ken Williams solved the above problem in his <CODE>Tie::DB_Lock</CODE> module, and I will present it in the next section.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Tie_DB_Lock">Tie::DB_Lock</A></H1></CENTER>
  -<P>
  -<CODE>Tie::DB_Lock</CODE> - ties hashes to databases using shared and exclusive locks. A module by
  -Ken Williams. which solves the problem raised in the previous section.
  -
  -<P>
  -The main difference from what I have described before is that
  -<CODE>Tie::DB_Lock</CODE> copies a dbm file on read so that reader processes do not have to keep the
  -file locked while they read it, and writers can still access it while
  -others are reading. It works best when you have lots of long-duration
  -reading, and a few short bursts of writing.
  -
  -<P>
  -The drawback of this module is a heavy IO performed when every reader makes
  -a fresh copy of the DB. With big dbm files this can be quite a disadvantage
  -and slowdown. An improvement that can cut a number of files that are being
  -copied, would be to have only one copy of the dbm image that will be shared
  -by all the reader processes. So it would put the responsibility of copying
  -the read-only file on the writer, not the reader. It would take some care
  -to make sure it does not disturb readers when putting a new read-only copy
  -into place.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Code_snippets">Code snippets</A></H1></CENTER>
  -<P>
  -I have discussed what can be achieved with mod_perl and dbm files, the cons
  -and pros. Now it is a time to show some code. I wrote a simple wrapper for
  -a <CODE>DB_File</CODE> module, and extended it to handle locking, and proper exits. Note that this
  -code still demands some testing, so be careful if you use it on your
  -production machine as is.
  -
  -<P>
  -So the <CODE>DB_File::Wrap</CODE> (note that you will not find it on CPAN):
  -
  -<P>
  -<PRE>  package DB_File::Wrap;
  -  require 5.004;
  +      # build the query
  +    my $do_sql = &quot;UPDATE $delayed $table SET &quot;;
  +    $do_sql   .= join &quot;,&quot;, 
  +      map { &quot;$_=&quot;.join &quot;&quot;,sql_quote(sql_escape($$r_data{$_})) } keys %{$r_data};
  +  
  +    my @where = ();
  +    for(my $i=0;$i&lt;@{$r_conds};$i=$i+2) {
  +      push @where, join &quot; &quot;,
  +        $$r_conds[$i],
  +        $$r_conds[$i+1][0],
  +        sql_quote(sql_escape($$r_conds[$i+1][1]));
  +    }
  +      # Add the where clause if we have one
  +    $do_sql .= &quot; WHERE &quot;. join &quot; AND &quot;, @where if @where;
  +  
  +  
  +    d(&quot;SQL: $do_sql&quot;);
  +  
  +      # do query
  +    $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
  +  
  +    $self-&gt;{sth}-&gt;execute();
  +  
  +  #  my ($count) = $self-&gt;{sth}-&gt;fetchrow_array;
  +  #
  +  #  d(&quot;Result: $count&quot;);
  +  
  +  } # end of sub sql_update_rows
  +  
  +  
  +  ######################################################################
  +  # delete rows from DB by condition
  +  #
  +  # sql_delete_rows($table_name,\@conditions);
  +  #
  +  # conditions must be an array so we can path more than one column with
  +  # the same name.
  +  #  @conditions =  ( column =&gt; ['comp_sign','value'],
  +  #                  foo    =&gt; ['&gt;',15],
  +  #                  foo    =&gt; ['&lt;',30],
  +  #                );
  +  #
  +  # * The sub knows automatically to detect and quote strings 
  +  #
  +  #
  +  ##########################
  +  sub sql_delete_rows{
  +    my $self    = shift;
  +    my $table   = shift || '';
  +    my $r_conds = shift || [];
  +  
  +      # we want to print in debug mode the trace
  +    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
     
  -  use strict;
  +      # build the query
  +    my $do_sql = &quot;DELETE FROM $table &quot;;
     
  -  BEGIN {
  -      # RCS/CVS complient:  must be all one line, for MakeMaker
  -    $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.12 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
  +    my @where = ();
  +    for(my $i=0;$i&lt;@{$r_conds};$i=$i+2) {
  +      push @where, join &quot; &quot;,
  +        $$r_conds[$i],
  +        $$r_conds[$i+1][0],
  +        sql_quote(sql_escape($$r_conds[$i+1][1]));
  +    }
     
  -  }
  +      # Must be very carefull with deletes, imagine somehow @where is
  +      # not getting set, &quot;DELETE FROM NAME&quot; deletes the contents of the table
  +    warn(&quot;Attempt to delete a whole table $table from DB\n!!!&quot;),return unless @where;
     
  -  use DB_File;
  -  use Fcntl qw(:flock O_RDWR O_CREAT);
  -  use Carp qw(croak carp verbose);
  -  use IO::File;
  +      # Add the where clause if we have one
  +    $do_sql .= &quot; WHERE &quot;. join &quot; AND &quot;, @where;
     
  -  use vars qw($debug);
  +    d(&quot;SQL: $do_sql&quot;);
     
  -  #$debug = 1;
  -  $debug = 0;
  +      # do query
  +    $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
  +    $self-&gt;{sth}-&gt;execute();
     
  -  # my $db = DB_File::Wrap \%hash, $filename, [lockmode];
  -  # from now one we can work with both %hash (tie API) and $db (direct API)
  -  #########
  -  sub new{
  -    my $class     = shift;
  -    my $hr_hash   = shift;
  -    my $file      = shift;
  -    my $lock_mode = shift || '';
  -    my $db_type   = shift || 'HASH';
  +  } # end of sub sql_delete_rows
     
  -    my $self;
  -    $self = bless {
  -                 db_type =&gt; 'DB_File',
  -                 flags   =&gt; O_RDWR|O_CREAT,
  -                 mode    =&gt; 0660,
  -                 hash    =&gt; $hr_hash,
  -                 how     =&gt; $DB_HASH,
  -                }, $class ;
     
  -      # by default we tie with HASH alg and if requested with BTREE
  -    $self-&gt;{'how'} = ($db_type eq 'BTREE') ? $DB_BTREE : $DB_HASH;
  +  ######################################################################
  +  # executes the passed query and returns a reference to an array which
  +  # contains one reference per row. If there are no rows to return,
  +  # returns a reference to an empty array.
  +  #
  +  # $r_array = sql_execute_and_get_r_array($query);
  +  #
  +  #
  +  ##########################
  +  sub sql_execute_and_get_r_array{
  +    my $self     = shift;
  +    my $do_sql   = shift || '';
     
  -      # tie the object
  -    $self-&gt;{'db_obj'} = tie %{$hr_hash},
  -      $self-&gt;{'db_type'},$file, $self-&gt;{'flags'},$self-&gt;{'mode'}, $self-&gt;{'how'}
  -        or croak &quot;Can't tie $file:$!\n&quot;; ;
  +      # we want to print in debug mode the trace
  +    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;);
     
  -    my $fd = $self-&gt;{'db_obj'}-&gt;fd;
  -    croak &quot;Can't get fd :$!&quot; unless defined $fd and $fd;
  -    $self-&gt;{'fh'}= new IO::File &quot;+&lt;&amp;=$fd&quot; or croak &quot;[&quot;.__PACKAGE__.&quot;] Can't dup: $!&quot;;
  +    d(&quot;SQL: $do_sql&quot;);
     
  -      # set the lock status to unlocked
  -    $self-&gt;{'lock'} = 0;
  +    $self-&gt;{dbh}-&gt;selectall_arrayref($do_sql);
     
  -      # do the lock here if requested
  -    $self-&gt;lock($lock_mode) if $lock_mode;
  +  } # end of sub sql_execute_and_get_r_array
     
  -    return $self;
     
  -  } # end of sub new
     
  +  #
  +  #
  +  # return current date formatted for a DATE field type
  +  # YYYYMMDD
  +  #
  +  ############
  +  sub sql_date{
  +    my $self     = shift;
     
  -  # lock the fd either exclusive or shared lock (write/read)
  -  # default is read (shared)
  -  ###########
  -  sub lock{
  -    my $self      = shift;
  -    my $lock_mode = shift || 'read';
  +    my ($sec,$min,$hour,$mday,$mon,$year) = localtime();
  +    $year = ($year&gt;70) ? sprintf &quot;19%0.2d&quot;,$year : sprintf &quot;20%0.2d&quot;,$year;
  +    return sprintf &quot;%0.4d%0.2d%0.2d&quot;,$year,++$mon,$mday;
     
  -  # lock codes:
  -  # 0 == not   locked
  -  # 1 == read  locked
  -  # 2 == write locked
  +  } # end of sub sql_date
     
  -    if ($lock_mode eq 'write') {
  -        # Get the exclusive write lock
  -      unless (flock ($self-&gt;{'fh'}, LOCK_EX | LOCK_NB)) {
  -        unless (flock ($self-&gt;{'fh'}, LOCK_EX)) { croak &quot;exclusive flock: $!&quot; }
  -      }
  -        # save the status of lock
  -      $self-&gt;{'lock'} = 2;
  +  #
  +  #
  +  # return current date formatted for a DATE field type
  +  # YYYYMMDDHHMMSS
  +  #
  +  ############
  +  sub sql_datetime{
  +    my $self     = shift;
     
  -    } elsif ($lock_mode eq 'read'){
  -        # Get the shared read lock
  -      unless (flock ($self-&gt;{'fh'}, LOCK_SH | LOCK_NB)) {
  -        unless (flock ($self-&gt;{'fh'}, LOCK_SH)) { croak &quot;shared flock: $!&quot; }
  -      }
  -        # save the status of lock
  -      $self-&gt;{'lock'} = 1;
  -    } else {
  -        # incorrect mode
  -      carp &quot;Can't lock. Unknown mode: $lock_mode\n&quot;;
  -    }
  +    my ($sec,$min,$hour,$mday,$mon,$year) = localtime();
  +    $year = ($year&gt;70) ? sprintf &quot;19%0.2d&quot;,$year : sprintf &quot;20%0.2d&quot;,$year;
  +    return sprintf &quot;%0.4d%0.2d%0.2d%0.2d%0.2d%0.2d&quot;,$year,++$mon,$mday,$hour,$min,$sec;
     
  -  } # end of sub lock
  +  } # end of sub sql_datetime
     
  -  # unlock 
  -  ###########
  -  sub unlock{
  -    my $self = shift;
     
  -    $self-&gt;{'db_obj'}-&gt;sync() if defined $self-&gt;{'db_obj'};   # flush
  -    flock($self-&gt;{'fh'}, LOCK_UN);
  -    $self-&gt;{'lock'} = 0;
  -  }
  +  # 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; } @_ }
     
  -  # untie the hash
  -  # and close all the handlers
  -  # if wasn't unlocked, end() will unlock as well
  +  # 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 }
  +  
  +  
  +  # DESTROY makes all kinds of cleanups if the fuctions were interuppted
  +  # before their completion and haven't had a chance to make a clean up.
     ###########
  -  sub end{
  +  sub DESTROY{
       my $self = shift;
     
  -      # unlock if stilllocked
  -    $self-&gt;unlock() if $self-&gt;{'lock'};
  +    $self-&gt;{sth}-&gt;finish     if defined $self-&gt;{sth} and $self-&gt;{sth};
  +    $self-&gt;{dbh}-&gt;disconnect if defined $self-&gt;{dbh} and $self-&gt;{dbh};
     
  -    delete $self-&gt;{'db_obj'}    if $self-&gt;{'db_obj'};
  -    untie %{$self-&gt;{'hr_hash'}} if $self-&gt;{'hr_hash'};
  -    $self-&gt;{'fh'}-&gt;close        if $self-&gt;{'fh'};
  +  } # end of sub DESTROY
  +  
  +  # Don't remove
  +  1;
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A></H2></CENTER>
  +<P>
  +In your code that wants to use <CODE>My::DB</CODE>, you have to create a
  +<CODE>My::DB</CODE> object first:
  +
  +<P>
  +<PRE>  use vars qw($db_obj);
  +  my $db_obj = new My::DB or croak &quot;Can't initialize My::DB object: $!\n&quot;;
  +</PRE>
  +<P>
  +From this moment, you can use any <CODE>My::DB</CODE>'s methods. I will start from a very simple query - I want to know where
  +the users are and produce statistics. <CODE>tracker</CODE> is the name of the table.
  +
  +<P>
  +<PRE>    # fetch the statistics of where users are
  +  my $r_ary = $db_obj-&gt;sql_get_matched_rows_ary_ref
  +    (&quot;tracker&quot;,
  +     [qw(where_user_are)],
  +    );
  +  
  +  my %stats = ();
  +  my $total = 0;
  +  foreach my $r_row (@$r_ary){
  +    $stats{$r_row-&gt;[0]}++;
  +    $total++;
  +  }
  +</PRE>
  +<P>
  +Now let's count how many users do we have (in <CODE>users</CODE> table):
  +
  +<P>
  +<PRE>  my $count = $db_obj-&gt;sql_count_matched(&quot;users&quot;);
  +</PRE>
  +<P>
  +Check whether user exists:
  +
  +<P>
  +<PRE>  my $username = 'stas';
  +  my $exists = $db_obj-&gt;sql_count_matched
  +  (&quot;users&quot;,
  +   [username =&gt; [&quot;=&quot;,$username]]
  +  );
  +</PRE>
  +<P>
  +Check whether user online and get time since when she is online (<CODE>since</CODE> a column in the <CODE>tracker</CODE> table telling since when user is online):
  +
  +<P>
  +<PRE>  my @row = ();
  +  $db_obj-&gt;sql_get_matched_row
  +  (\@row,
  +   &quot;tracker&quot;,
  +   ['UNIX_TIMESTAMP(since)'],
  +   [username =&gt; [&quot;=&quot;,$username]]
  +  );
  +  
  +  if (@row) {
  +    my $idle = int( (time() - $row[0]) / 60);
  +    return &quot;Current status: Is Online and idle for $idle minutes.&quot;;
  +  }
  +</PRE>
  +<P>
  +A complex query. I do join of 2 tables, and want to get a reference to
  +array, which will store a slice of the matched query (<CODE>LIMIT
  +$offset,$hits</CODE>), sorted by <CODE>username</CODE> and each row in array_ref to include the fields from the <CODE>users</CODE> table, but only those listed in
  +<CODE>@verbose_cols</CODE>. Then we print it out.
  +
  +<P>
  +<PRE>  my $r_ary = $db_obj-&gt;sql_get_matched_rows_ary_ref
  +    (
  +     &quot;tracker STRAIGHT_JOIN users&quot;,
  +     [map {&quot;users.$_&quot;} @verbose_cols],
  +     [],
  +     [&quot;WHERE tracker.username=users.username&quot;,
  +      &quot;ORDER BY users.username&quot;,
  +      &quot;LIMIT $offset,$hits&quot;],
  +    );
     
  +  foreach my $r_row (@$r_ary){
  +    print ...
  +  }
  +</PRE>
  +<P>
  +Another complex query. User checks checkboxes to be queried by, selects
  +from lists and types in match strings, we process input and build the <CODE>@where</CODE> array. Then we want to get the number of matches and the matched rows as
  +well.
  +
  +<P>
  +<PRE>  my @where = ();
  +    # process chekoxes - we turn them into REGEXP
  +  foreach (keys %search_keys) {
  +    next unless defined $q-&gt;param($_) and $q-&gt;param($_);
  +    my $regexp = &quot;[&quot;.join(&quot;&quot;,$q-&gt;param($_)).&quot;]&quot;;
  +    push @where, ($_ =&gt; ['REGEXP',$regexp]);
     }
  -  
  -  
  -  # DESTROY makes all kinds of cleanups if the fuctions were interuppted
  -  # before their completion and haven't had a chance to make a clean up.
  -  ###########
  -  sub DESTROY{
  -    my $self = shift;
  -  
  -      # just to be sure that we properly closed everything
  -    $self-&gt;end();
     
  -    print &quot;Destroying &quot;.__PACKAGE__.&quot;\n&quot; if $debug;
  -    undef $self if $self;
  +    # Now add all the single answer , selected =&gt; exact macth
  +  push @where,(country =&gt; ['=',$q-&gt;param('country')]) if $q-&gt;param('country');
     
  +    # Now add all the typed params
  +  foreach (qw(city state)) {
  +    push @where,($_ =&gt; ['LIKE',$q-&gt;param($_)]) if $q-&gt;param($_);
     }
  -  
  -  ####
  -  END {
     
  -    print &quot;Calling the END from &quot;.__PACKAGE__.&quot;\n&quot; if $debug;
  +     # Do the count all matched query
  +  my $total_matched_users =  $db_obj-&gt;sql_count_matched
  +    (
  +     &quot;users&quot;,
  +     \@where,
  +    );
     
  -  }
  +    # Now process the orderby
  +  my $orderby = $q-&gt;param('orderby') || 'username';
     
  -  1;
  -</PRE>
  -<P>
  -And you use it :
  -
  -<P>
  -<PRE>  use DB_File::Wrap ();
  +     # Do the query and fetch the data
  +  my $r_ary = $db_obj-&gt;sql_get_matched_rows_ary_ref
  +  (
  +   &quot;users&quot;,
  +   \@display_columns,
  +   \@where,
  +   [&quot;ORDER BY $orderby&quot;,
  +    &quot;LIMIT $offset,$hits&quot;],
  +  );
   </PRE>
   <P>
  -A simple tie, READ lock and untie
  +<CODE>sql_get_matched_rows_ary_ref</CODE> knows to handle both <CODE>OR</CODE>ed and
  +<CODE>AND</CODE>ed params. This example shows how to use <CODE>OR</CODE> on parameters:
   
  -<P>
  -<PRE>  my %mydb = ();
  -  my $db = new DB_File::Wrap \%mydb, $dbfile, 'read';
  -  print $mydb{'stas'} if exists $mydb{'stas'};
  -    # sync and untie
  -  $db-&gt;end();
  -</PRE>
   <P>
  -You can even skip the <CODE>end()</CODE> call, if leave the scope <CODE>$db</CODE> defined in:
  +This snippet is an implementation of the watchdog. Users register usernames
  +of the people they want to know when these are going online, so we have to
  +make 2 queries - one to get a list of these usernames, second to query
  +whether any of these users is online. In the second query we use <CODE>OR</CODE> keyword.
   
   <P>
  -<PRE>  sub user_exists{
  -    my $user = shift;
  -    my $result = 0;
  +<PRE>  # check who we are looking for
  +  $r_ary = $db_obj-&gt;sql_get_matched_rows_ary_ref
  +    (&quot;watchdog&quot;,
  +     [qw(watched)],
  +     [username =&gt; ['=',$username)],
  +     ],
  +    );
     
  -    my %mydb = ();
  -    my $db = new DB_File::Wrap \%mydb, $dbfile, 'read';
  +    # put them into an array
  +  my @watched = map {$_-&gt;[0]} @{$r_ary};
     
  -    # if we match the username return 1
  -    $result = 1 if $mydb{$user};
  +  my %matched = ();
  +    # Do user has some registered usernames?
  +  if (@watched) {
     
  -    $result;
  -  } # end of sub user_exists
  -</PRE>
  -<P>
  -Perform both, read and write operations:
  -
  -<P>
  -<PRE>  my %mydb = ();
  -  my $db = new DB_File::Wrap \%mydb, $dbfile;
  -  print $mydb{'stas'} if exists $mydb{'stas'};
  +  # try to bring all the users who match (exactly) the usernames - put
  +  # it into array and compare with a hash!
  +    $r_ary = $db_obj-&gt;sql_get_matched_rows_ary_ref
  +      (&quot;tracker&quot;,
  +       [qw(username)],
  +       [username =&gt; ['=',\@watched],
  +       ]
  +      );
     
  -    # lock the db, we gonna change it!
  -  $db-&gt;lock('write');
  -  $mydb{'stas'} = 1;
  -    # unlock the db for write
  +    map {$matched{$_-&gt;[0]} = 1} @{$r_ary};
  +  }
     
  -    # sync and untie
  -  $db-&gt;end();
  +  # Now %matched includes the usernames of the users who are being
  +  # watched by $username and currently are online.
   </PRE>
  -<P>
  -If your CGI was interrupted in the middle, <CODE>DESTROY</CODE> block will worry to unlock the dbm file and flush the changes. Note that I
  -have got db corruptions even with this code on huge dbm files 10000+
  -records, so be careful when you use it. I thought that I have covered all
  -the possible failures but seems that not all of them. At the end I have
  -moved everything to work with <STRONG>mysql</STRONG>. So if you figure out where the problem is you are very welcome to tell me
  -about it.
  -
   <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>
  @@ -11306,7 +11629,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="databases.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="multiuser.html">Next</A>      ]
  +	     [    <A HREF="security.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="dbm.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -11319,7 +11642,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/05/1999
         </FONT>
       </B>
     </TD>
  @@ -11346,7 +11669,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: mod_perl for ISPs. mod_perl and Virtual Hosts.</TITLE>
  +   <TITLE>mod_perl guide: mod_perl and dbm files</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -11368,14 +11691,17 @@
   <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>
  -mod_perl for ISPs. mod_perl and Virtual Hosts.</H1>
  +mod_perl and dbm files</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="dbm.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="databases.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="multiuser.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#ISPs_providing_mod_perl_services">ISPs providing mod_perl services - a fantasy or reality.</A>
  -	<LI><A HREF="#Virtual_Hosts_in_the_guide">Virtual Hosts in the guide</A>
  +	<LI><A HREF="#Where_and_Why_to_use_dbm_files">Where and Why to use dbm files</A>
  +	<LI><A HREF="#mod_perl_and_dbm">mod_perl and dbm</A>
  +	<LI><A HREF="#Locking_dbm_handlers">Locking dbm handlers</A>
  +	<LI><A HREF="#Tie_DB_Lock">Tie::DB_Lock</A>
  +	<LI><A HREF="#Code_snippets">Code snippets</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -11393,171 +11719,398 @@
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="ISPs_providing_mod_perl_services">ISPs providing mod_perl services - a fantasy or reality.</A></H1></CENTER>
  +<CENTER><H1><A NAME="Where_and_Why_to_use_dbm_files">Where and Why to use dbm files</A></H1></CENTER>
   <P>
  -You have fallen in love with mod_perl from the first sight, since the
  -moment you have installed it at your home box. But when you wanted to
  -convert your CGI scripts, currently running on your favorite ISPs machine,
  -to run under mod_perl - you have discovered, your ISPs either have never
  -heard of such a beast, or refuse to install it for you.
  +dbm files are the first implementations of the databases, which originated
  +on Unix systems, and currently being used in many Unix applications where
  +simple key-value pairs should be stored and manipulated. As of this writing
  +Berkeley DB is the most powerful dbm implementation. If you need a light
  +database, with easy API to work with this is a solution that should be
  +considered as a first one. Of course only if you are sure the DB you are
  +going to use will stay small, I would say under 5000-10000 records, but it
  +depends on your hardware, which can rise and lower the numbers above. It is
  +a much better solution over the flat file databases which become pretty
  +slow on insert, update and delete operations when the number of records
  +grows beyond 1000. The situation is even worse when we need to run sort on
  +this kind of DB.
   
   <P>
  -You are an old sailor in the ISP business, you have seen it all, you know
  -how many ISPs are out there and you know that the sales margins are too low
  -to keep you happy. You are looking for some new service almost no one
  -provides, to attract more clients to become your users and hopefully to
  -have a bigger slice than a neighbor ISP.
  +dbm files are being manipulated much faster than their flat file brothers,
  +since almost never the whole DB is being read into a memory and because of
  +smart storage technique. You can use a <CODE>HASH</CODE>
  +algorithm which allows a <CODE>0(1)</CODE> complexity of search and update, fast insert and delete, but slow sort,
  +since you have to do it yourself. <CODE>BTREE</CODE> allows arbitrary key/value pairs to be stored in a sorted, balanced binary
  +tree, which allows us to get a sorted sequence of data pairs in <CODE>0(1)</CODE>, but much slower insert, update, delete operations. <CODE>RECNO</CODE> algorithm is more complicated one, and enables for both fixed-length and
  +variable-length flat text files to be manipulated using the same key/value
  +pair interface as in <CODE>HASH</CODE> and
  +<CODE>BTREE</CODE>. In this case the key will consist of a record (line) number. Most chances
  +you will want to use the <CODE>HASH</CODE> format, but your choice is very dependent on a kind of your application.
   
   <P>
  -If you are a user asking for a mod_perl service or an ISP considering to
  -provide this service, this section should make things clear for both of
  -you.
  +<STRONG>dbm</STRONG> databases are not limited for key and value pairs storages, but can store
  +more complicated structures with help of <CODE>MLDBM</CODE>
  +module. Which can dump and restore the whole symbol table of your script,
  +including arrays, hashes and other complicated data <CODE>HASH</CODE>
  +structures.
  +
  +<P>
  +Another important thing to say, is that you cannot convert a dbm file from
  +one storing algorithm to another, by simply tying it using a wanted format.
  +The only way is to dump it into a flat file and then restore it using a new
  +format. You can use a script like:
  +
  +<P>
  +<PRE>  #!/usr/bin/perl -w
  +  
  +  #
  +  # This script gets as a parameter a Berkeley DB file(s) which is stored
  +  # with DB_BTREE algorithm, and will backup it with .bak and create
  +  # instead the db with the same records but stored with DB_HASH
  +  # algorithm
  +  #
  +  # Usage: btree2hash.pl filename(s)
  +  
  +  use strict;
  +  use DB_File;
  +  use File::Copy;
  +  
  +    # Do checks 
  +  die &quot;Usage: btree2hash.pl filename(s))\n&quot; unless @ARGV;
  +  
  +  foreach my $filename (@ARGV) {
  +  
  +    die &quot;Can't find $filename: $!\n&quot; unless -e $filename and -r $filename;
  +  
  +      # First backup the filename
  +    move(&quot;$filename&quot;,&quot;$filename.btree&quot;) 
  +      or die &quot;can't move $filename $filename.btree:$!\n&quot;;
  +  
  +    my %hash;
  +    my %btree;
  +  
  +      # tie both dbs (db_hash is a fresh one!)
  +    tie %btree , 'DB_File',&quot;$filename.btree&quot;, O_RDWR|O_CREAT, 
  +        0660, $DB_BTREE or die &quot;Can't tie %btree&quot;;
  +    tie %hash ,  'DB_File',&quot;$filename&quot; , O_RDWR|O_CREAT, 
  +        0660, $DB_HASH  or die &quot;Can't tie %hash&quot;;
  +  
  +      # copy DB
  +    %hash = %btree;
  +  
  +      # untie
  +    untie %btree ;
  +    untie %hash ;
  +  }
  +</PRE>
  +<P>
  +Note that some dbm implementations come with other conversion utilities as
  +well.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="mod_perl_and_dbm">mod_perl and dbm</A></H1></CENTER>
  +<P>
  +Where mod_perl enters into a picture? If you are using a read only dbm file
  +you can have it work faster if you keep it open (tied) all the time, so
  +when your CGI script wants to access the database it is already tied and
  +ready to be used. It will work as well with your dynamic dbm databases as
  +well but you need to use locking to avoid data corruptions. Of course this
  +feature can make a huge speedup to your CGIs, but you should be very
  +careful. What should be taken into account is a db locking, handling
  +possible <CODE>die()</CODE> cases and child quits. A stale lock can deactivate your whole site, if your
  +locking mechanism cannot handle dropped locks. You can enter a deadlock
  +situations if 2 processes are trying to acquire locks on 2 databases, but
  +get stuck because each has got hands on one of the 2 databases, and to
  +release it, each process needs the second one, which will never be freed,
  +because that is the condition for the first one to be released (possible
  +only if processes do not all ask for their DB files in the same order). If
  +you modify the DB you should be very careful to flush and synchronize it,
  +especially when your CGI unexpectedly dies. In general your application
  +should be tested very thoroughly before you put it into production to
  +handle important data.
   
   <P>
  -an ISP has 3 choices to choose from:
  -
  -<OL>
  -<P><LI>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Locking_dbm_handlers">Locking dbm handlers</A></H1></CENTER>
   <P>
  -ISP cannot afford having a user, running scripts under mod_perl, on the
  -main server, since it will die very soon for one of the many reasons:
  -either sloppy programming, or user testing just updated script which
  -probably has some syntax errors and etc, no need to explain why if you are
  -familiar with mod_perl peculiarities. The only scripts that <STRONG>CAN BE ALLOWED</STRONG> to use, are the ones that were written by ISP and are not being modified by
  -user (guest books, counters and etc - the same standard scripts ISPs
  -providing since they were born). So you have to say <STRONG>NO</STRONG> for this choice.
  +Let's have a lock status as a global variable, so it will persist from
  +request to request. If we are requesting a lock - READ (shared) or WRITE
  +(exclusive), the current lock status is being obtained first.
   
  -<P><LI>
   <P>
  -But, hey why I cannot let my user to run his own server, so I clean my
  -hands off and do not care how dirty and sloppy user's code is (assuming
  -that user is running the server by his own username).
  +If we get a READ lock request, it is granted as soon as file becomes or is
  +locked or already locked for READ. Lock status is READ now.
   
   <P>
  -This option is fine as long as you are concerned about your new system
  -requirements. If you have even some very limited experience with mod_perl,
  -you know that mod_perl enabled apache servers while freeing up your CPU and
  -lets you run scripts much much faster, has a huge memory demands (5-20
  -times the plain apache uses). The size depends on the code length,
  -sloppiness of the programmer, possible memory leaks the code might have and
  -all that multiplied by the number of children each server spawns. A very
  -simple example : a server demanding 10Mb of memory which spawns 10
  -children, already rises your memory requirements by 100Mb (the real
  -requirement are actually smaller if your OS allows code sharing between
  -processes and a programmer exploits these features in her code). Now
  -multiply the received number by the number of users you intend to have and
  -you will get the memory requirements. Since ISPs never say no, you better
  -use an opposite approach - think of a largest memory size you can afford
  -then divide it by one user's requirements as I have shown in example, and
  -you will know how much mod_perl users you can afford :)
  +If we get a WRITE lock request, it is granted as soon as file becomes or is
  +unlocked. Lock status is WRITE now.
   
   <P>
  -But who am I to prognosticate how much memory your user may use. His
  -requirement from a single server can be very modest, but do you know how
  -many of servers he will run (after all she has all the control over
  -httpd.conf - and it has to be that way, since this is very essential for
  -the user running mod_perl)?
  +What happens to the WRITE lock request, is the most important. If the DB is
  +being READ locked, request that request to write will poll until there will
  +be no reading or writing process left. Lots of processes can successfully
  +read the file, since they do not block each other from doing so. This means
  +that a process that wants to write to the file (first obtaining an
  +exclusive lock) never gets a chance to squeeze in. The following diagram
  +represents a possible scenario where everybody read but no one can write:
   
   <P>
  -All this rumbling about memory leads to a single question: Can you restrict
  -user from using more than X memory? Or another variation of the question:
  -Assuming you have as much memory as you want, can you charge user for the
  -average memory usage?
  +<PRE>  [-p1-]                 [--p1--]
  +     [--p2--]
  +   [---------p3---------]
  +                 [------p4-----]
  +     [--p5--]   [----p5----]
  +</PRE>
  +<P>
  +So you get a starving process, which most certainly will timeout the
  +request, and the DB will be not updated.
   
   <P>
  -If the answer for either of the above question is positive, you are all set
  -and your clients will prize your name for letting them run mod_perl! There
  -are tools to restrict resources' usage (See for example man pages for <CODE>ulimit(3)</CODE>, <CODE>getrlimit(2)</CODE>, <CODE>setrlimit(2)</CODE>
  -and <CODE>sysconf(3)</CODE> ).
  +So you have another reason not to cache the dbm handle with dynamic dbm
  +files. But it will work perfect with the static DBM files without a need to
  +lock files at all. Ken Williams solved the above problem in his <CODE>Tie::DB_Lock</CODE> module, and I will present it in the next section.
   
   <P>
  -&lt;META&gt; If you have an experience with some restriction techniques
  -please share with us. Thank you! &lt;/META&gt;
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Tie_DB_Lock">Tie::DB_Lock</A></H1></CENTER>
  +<P>
  +<CODE>Tie::DB_Lock</CODE> - ties hashes to databases using shared and exclusive locks. A module by
  +Ken Williams. which solves the problem raised in the previous section.
   
   <P>
  -If you have picked this choice, you have to provide your client:
  +The main difference from what I have described before is that
  +<CODE>Tie::DB_Lock</CODE> copies a dbm file on read so that reader processes do not have to keep the
  +file locked while they read it, and writers can still access it while
  +others are reading. It works best when you have lots of long-duration
  +reading, and a few short bursts of writing.
   
  -<UL>
  -<P><LI>
   <P>
  -Shutdown/startup scripts installed together with the rest of your daemon
  -startup scripts (e.g <CODE>/etc/rc.d</CODE> directory) scripts, so when you reboot your machine user's server will be
  -correctly shutdowned and will be back online the moment your system comes
  -back online. Also make sure to start each server under username the server
  -belongs to, if you are not looking for a big trouble.
  +The drawback of this module is a heavy IO performed when every reader makes
  +a fresh copy of the DB. With big dbm files this can be quite a disadvantage
  +and slowdown. An improvement that can cut a number of files that are being
  +copied, would be to have only one copy of the dbm image that will be shared
  +by all the reader processes. So it would put the responsibility of copying
  +the read-only file on the writer, not the reader. It would take some care
  +to make sure it does not disturb readers when putting a new read-only copy
  +into place.
   
  -<P><LI>
   <P>
  -Proxy (in a forward or httpd accelerator mode) services for user's virtual
  -host. Since user will have to run her server on unprivileged port
  -(&gt;1024), you will have to forward all requests from
  -<CODE>user.given.virtual.hostname:80</CODE> (which is
  -<CODE>user.given.virtual.hostname</CODE> without port - 80 is a default) to
  -<CODE>your.machine.ip:port_assigned_to_user</CODE> and user to code his scripts to write self referencing URLs to be of <CODE>user.given.virtual.hostname</CODE>
  -base of course.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Code_snippets">Code snippets</A></H1></CENTER>
  +<P>
  +I have discussed what can be achieved with mod_perl and dbm files, the cons
  +and pros. Now it is a time to show some code. I wrote a simple wrapper for
  +a <CODE>DB_File</CODE> module, and extended it to handle locking, and proper exits. Note that this
  +code still demands some testing, so be careful if you use it on your
  +production machine as is.
   
   <P>
  -Letting user to run a mod_perl server, immediately adds a requirement for
  -user to be able to restart and configure their own server. But only root
  -can bind port 80. That is why user has to use ports numbers &gt;1024.
  +So the <CODE>DB_File::Wrap</CODE> (note that you will not find it on CPAN):
   
  -<P><LI>
  +<P>
  +<PRE>  package DB_File::Wrap;
  +  require 5.004;
  +  
  +  use strict;
  +  
  +  BEGIN {
  +      # RCS/CVS complient:  must be all one line, for MakeMaker
  +    $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.13 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
  +  
  +  }
  +  
  +  use DB_File;
  +  use Fcntl qw(:flock O_RDWR O_CREAT);
  +  use Carp qw(croak carp verbose);
  +  use IO::File;
  +  
  +  use vars qw($debug);
  +  
  +  #$debug = 1;
  +  $debug = 0;
  +  
  +  # my $db = DB_File::Wrap \%hash, $filename, [lockmode];
  +  # from now one we can work with both %hash (tie API) and $db (direct API)
  +  #########
  +  sub new{
  +    my $class     = shift;
  +    my $hr_hash   = shift;
  +    my $file      = shift;
  +    my $lock_mode = shift || '';
  +    my $db_type   = shift || 'HASH';
  +  
  +    my $self;
  +    $self = bless {
  +                 db_type =&gt; 'DB_File',
  +                 flags   =&gt; O_RDWR|O_CREAT,
  +                 mode    =&gt; 0660,
  +                 hash    =&gt; $hr_hash,
  +                 how     =&gt; $DB_HASH,
  +                }, $class ;
  +  
  +      # by default we tie with HASH alg and if requested with BTREE
  +    $self-&gt;{'how'} = ($db_type eq 'BTREE') ? $DB_BTREE : $DB_HASH;
  +  
  +      # tie the object
  +    $self-&gt;{'db_obj'} = tie %{$hr_hash},
  +      $self-&gt;{'db_type'},$file, $self-&gt;{'flags'},$self-&gt;{'mode'}, $self-&gt;{'how'}
  +        or croak &quot;Can't tie $file:$!\n&quot;; ;
  +  
  +    my $fd = $self-&gt;{'db_obj'}-&gt;fd;
  +    croak &quot;Can't get fd :$!&quot; unless defined $fd and $fd;
  +    $self-&gt;{'fh'}= new IO::File &quot;+&lt;&amp;=$fd&quot; or croak &quot;[&quot;.__PACKAGE__.&quot;] Can't dup: $!&quot;;
  +  
  +      # set the lock status to unlocked
  +    $self-&gt;{'lock'} = 0;
  +  
  +      # do the lock here if requested
  +    $self-&gt;lock($lock_mode) if $lock_mode;
  +  
  +    return $self;
  +  
  +  } # end of sub new
  +  
  +  
  +  # lock the fd either exclusive or shared lock (write/read)
  +  # default is read (shared)
  +  ###########
  +  sub lock{
  +    my $self      = shift;
  +    my $lock_mode = shift || 'read';
  +  
  +  # lock codes:
  +  # 0 == not   locked
  +  # 1 == read  locked
  +  # 2 == write locked
  +  
  +    if ($lock_mode eq 'write') {
  +        # Get the exclusive write lock
  +      unless (flock ($self-&gt;{'fh'}, LOCK_EX | LOCK_NB)) {
  +        unless (flock ($self-&gt;{'fh'}, LOCK_EX)) { croak &quot;exclusive flock: $!&quot; }
  +      }
  +        # save the status of lock
  +      $self-&gt;{'lock'} = 2;
  +  
  +    } elsif ($lock_mode eq 'read'){
  +        # Get the shared read lock
  +      unless (flock ($self-&gt;{'fh'}, LOCK_SH | LOCK_NB)) {
  +        unless (flock ($self-&gt;{'fh'}, LOCK_SH)) { croak &quot;shared flock: $!&quot; }
  +      }
  +        # save the status of lock
  +      $self-&gt;{'lock'} = 1;
  +    } else {
  +        # incorrect mode
  +      carp &quot;Can't lock. Unknown mode: $lock_mode\n&quot;;
  +    }
  +  
  +  } # end of sub lock
  +  
  +  # unlock 
  +  ###########
  +  sub unlock{
  +    my $self = shift;
  +  
  +    $self-&gt;{'db_obj'}-&gt;sync() if defined $self-&gt;{'db_obj'};   # flush
  +    flock($self-&gt;{'fh'}, LOCK_UN);
  +    $self-&gt;{'lock'} = 0;
  +  }
  +  
  +  # untie the hash
  +  # and close all the handlers
  +  # if wasn't unlocked, end() will unlock as well
  +  ###########
  +  sub end{
  +    my $self = shift;
  +  
  +      # unlock if stilllocked
  +    $self-&gt;unlock() if $self-&gt;{'lock'};
  +  
  +    delete $self-&gt;{'db_obj'}    if $self-&gt;{'db_obj'};
  +    untie %{$self-&gt;{'hr_hash'}} if $self-&gt;{'hr_hash'};
  +    $self-&gt;{'fh'}-&gt;close        if $self-&gt;{'fh'};
  +  
  +  }
  +  
  +  
  +  # DESTROY makes all kinds of cleanups if the fuctions were interuppted
  +  # before their completion and haven't had a chance to make a clean up.
  +  ###########
  +  sub DESTROY{
  +    my $self = shift;
  +  
  +      # just to be sure that we properly closed everything
  +    $self-&gt;end();
  +  
  +    print &quot;Destroying &quot;.__PACKAGE__.&quot;\n&quot; if $debug;
  +    undef $self if $self;
  +  
  +  }
  +  
  +  ####
  +  END {
  +  
  +    print &quot;Calling the END from &quot;.__PACKAGE__.&quot;\n&quot; if $debug;
  +  
  +  }
  +  
  +  1;
  +</PRE>
   <P>
  -Another problem you will have to solve is how to assign ports between
  -users. Since user can pick any port above 1024 to run his server on, you
  -will have to make some regulation here. A simple example will stress the
  -importance of this problem: I am a malicious user or I just a rival of some
  -fellow who runs his own server on your ISP. All I should do is to find out
  -what port his server is listening to (e.g. with help of <CODE>netstat(8)</CODE>) and configure my own server to listen on the same port. While I am unable
  -to bind to this same port, imagine what will happen when you reboot your
  -system and my startup script happen to be run before my rivals! I get the
  -port first, now all requests will be redirected to my server and let your
  -imagination go wild about what nasty things might happen then. Of course
  -the ugly things will be revealed pretty soon, but the damage has been done.
  +And you use it :
   
  -</UL>
  -<P><LI>
   <P>
  -A much better, but costly solution is <STRONG>co-location</STRONG>. Let user to hook her (or ISP's) stand alone machine into your network,
  -and forget about this user. Of course either user or you will have to make
  -all the system administration chores and it will cost your client more
  -money.
  -
  +<PRE>  use DB_File::Wrap ();
  +</PRE>
   <P>
  -All in all, who are the people who seek the mod_perl support? The ones who
  -run serious projects/businesses, who can afford a stand alone box, thus
  -gaining their goal of self autonomy and keeping their ISP happy. So money
  -is not an obstacle.
  +A simple tie, READ lock and untie
   
  -</OL>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Virtual_Hosts_in_the_guide">Virtual Hosts in the guide</A></H1></CENTER>
  -<P>
  -If you are about to use <STRONG>Virtual Hosts</STRONG> you might want to read these sections:
  -
  +<PRE>  my %mydb = ();
  +  my $db = new DB_File::Wrap \%mydb, $dbfile, 'read';
  +  print $mydb{'stas'} if exists $mydb{'stas'};
  +    # sync and untie
  +  $db-&gt;end();
  +</PRE>
   <P>
  -<A HREF="././config.html#Perl_Sections">Perl Sections</A>.
  +You can even skip the <CODE>end()</CODE> call, if leave the scope <CODE>$db</CODE> defined in:
   
   <P>
  -<A HREF="././config.html#Configuring_Apache_mod_perl_wi">Easing the chores of configuring the virtual hosts with mod_macro</A>
  -
  -
  -
  +<PRE>  sub user_exists{
  +    my $user = shift;
  +    my $result = 0;
  +  
  +    my %mydb = ();
  +    my $db = new DB_File::Wrap \%mydb, $dbfile, 'read';
  +  
  +    # if we match the username return 1
  +    $result = 1 if $mydb{$user};
  +  
  +    $result;
  +  } # end of sub user_exists
  +</PRE>
   <P>
  -<A HREF="././config.html#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>
  -
  -
  +Perform both, read and write operations:
   
   <P>
  -<A HREF="././config.html#Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host basis</A>
  -
  -
  -
  +<PRE>  my %mydb = ();
  +  my $db = new DB_File::Wrap \%mydb, $dbfile;
  +  print $mydb{'stas'} if exists $mydb{'stas'};
  +  
  +    # lock the db, we gonna change it!
  +  $db-&gt;lock('write');
  +  $mydb{'stas'} = 1;
  +    # unlock the db for write
  +  
  +    # sync and untie
  +  $db-&gt;end();
  +</PRE>
   <P>
  -<A HREF="././config.html#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>
  -
  -
  +If your CGI was interrupted in the middle, <CODE>DESTROY</CODE> block will worry to unlock the dbm file and flush the changes. Note that I
  +have got db corruptions even with this code on huge dbm files 10000+
  +records, so be careful when you use it. I thought that I have covered all
  +the possible failures but seems that not all of them. At the end I have
  +moved everything to work with <STRONG>mysql</STRONG>. So if you figure out where the problem is you are very welcome to tell me
  +about it.
   
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -11569,7 +12122,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="dbm.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A>      ]
  +	     [    <A HREF="databases.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="multiuser.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -11582,7 +12135,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 05/08/1999
         </FONT>
       </B>
     </TD>
  @@ -11609,7 +12162,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: mod_perl for ISPs. mod_perl and Virtual Hosts.</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -11631,22 +12184,14 @@
   <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>
  +mod_perl for ISPs. mod_perl and Virtual Hosts.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="multiuser.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="status.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="dbm.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="status.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 to eat up all the disk's space, when it goes wild.</A>
  +	<LI><A HREF="#ISPs_providing_mod_perl_services">ISPs providing mod_perl services - a fantasy or reality.</A>
  +	<LI><A HREF="#Virtual_Hosts_in_the_guide">Virtual Hosts in the guide</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -11657,906 +12202,760 @@
   	     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="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
  +	     href="http://www.amazon.com/exec/obidos/ASIN/156592567X/writinapachemodu">
  +	     Amazon.com</a>.
   
  -<P>
  -Start httpd
  +	     <HR>
   
  +	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<PRE>        % /usr/apps/sbin/httpd_perl/apachectl start 
  -</PRE>
  +<CENTER><H1><A NAME="ISPs_providing_mod_perl_services">ISPs providing mod_perl services - a fantasy or reality.</A></H1></CENTER>
   <P>
  -Stop httpd
  +You have fallen in love with mod_perl from the first sight, since the
  +moment you have installed it at your home box. But when you wanted to
  +convert your CGI scripts, currently running on your favorite ISPs machine,
  +to run under mod_perl - you have discovered, your ISPs either have never
  +heard of such a beast, or refuse to install it for you.
   
  -<P>
  -<PRE>        % /usr/apps/sbin/httpd_perl/apachectl stop
  -</PRE>
   <P>
  -Restart httpd if running by sending a SIGHUP or start if not running
  +You are an old sailor in the ISP business, you have seen it all, you know
  +how many ISPs are out there and you know that the sales margins are too low
  +to keep you happy. You are looking for some new service almost no one
  +provides, to attract more clients to become your users and hopefully to
  +have a bigger slice than a neighbor ISP.
   
   <P>
  -<PRE>        % /usr/apps/sbin/httpd_perl/apachectl restart
  -</PRE>
  -<P>
  -Do a graceful restart by sending a SIGUSR1 or start if not running
  +If you are a user asking for a mod_perl service or an ISP considering to
  +provide this service, this section should make things clear for both of
  +you.
   
  -<P>
  -<PRE>        % /usr/apps/sbin/httpd_perl/apachectl graceful    
  -</PRE>
   <P>
  -Do a configuration syntax test:
  +an ISP has 3 choices to choose from:
   
  -<P>
  -<PRE>        % /usr/apps/sbin/httpd_perl/apachectl configtest 
  -</PRE>
  +<OL>
  +<P><LI>
   <P>
  -See the next section for the implication of the above calls.
  +ISP cannot afford having a user, running scripts under mod_perl, on the
  +main server, since it will die very soon for one of the many reasons:
  +either sloppy programming, or user testing just updated script which
  +probably has some syntax errors and etc, no need to explain why if you are
  +familiar with mod_perl peculiarities. The only scripts that <STRONG>CAN BE ALLOWED</STRONG> to use, are the ones that were written by ISP and are not being modified by
  +user (guest books, counters and etc - the same standard scripts ISPs
  +providing since they were born). So you have to say <STRONG>NO</STRONG> for this choice.
   
  +<P><LI>
   <P>
  -Replace 'httpd_perl' with 'httpd_docs' in the above calls to control the
  -httpd_docs server.
  +But, hey why I cannot let my user to run his own server, so I clean my
  +hands off and do not care how dirty and sloppy user's code is (assuming
  +that user is running the server by his own username).
   
   <P>
  -There are other options for <STRONG>apachectl</STRONG>, use 'help' option to see them all.
  +This option is fine as long as you are concerned about your new system
  +requirements. If you have even some very limited experience with mod_perl,
  +you know that mod_perl enabled apache servers while freeing up your CPU and
  +lets you run scripts much much faster, has a huge memory demands (5-20
  +times the plain apache uses). The size depends on the code length,
  +sloppiness of the programmer, possible memory leaks the code might have and
  +all that multiplied by the number of children each server spawns. A very
  +simple example : a server demanding 10Mb of memory which spawns 10
  +children, already rises your memory requirements by 100Mb (the real
  +requirement are actually smaller if your OS allows code sharing between
  +processes and a programmer exploits these features in her code). Now
  +multiply the received number by the number of users you intend to have and
  +you will get the memory requirements. Since ISPs never say no, you better
  +use an opposite approach - think of a largest memory size you can afford
  +then divide it by one user's requirements as I have shown in example, and
  +you will know how much mod_perl users you can afford :)
   
   <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.
  +But who am I to prognosticate how much memory your user may use. His
  +requirement from a single server can be very modest, but do you know how
  +many of servers he will run (after all she has all the control over
  +httpd.conf - and it has to be that way, since this is very essential for
  +the user running mod_perl)?
   
   <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.)
  +All this rumbling about memory leads to a single question: Can you restrict
  +user from using more than X memory? Or another variation of the question:
  +Assuming you have as much memory as you want, can you charge user for the
  +average memory usage?
   
  -<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.
  +If the answer for either of the above question is positive, you are all set
  +and your clients will prize your name for letting them run mod_perl! There
  +are tools to restrict resources' usage (See for example man pages for <CODE>ulimit(3)</CODE>, <CODE>getrlimit(2)</CODE>, <CODE>setrlimit(2)</CODE>
  +and <CODE>sysconf(3)</CODE> ).
   
   <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.
  +&lt;META&gt; If you have an experience with some restriction techniques
  +please share with us. Thank you! &lt;/META&gt;
   
   <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>
  +If you have picked this choice, you have to provide your client:
  +
  +<UL>
  +<P><LI>
   <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>
  +Shutdown/startup scripts installed together with the rest of your daemon
  +startup scripts (e.g <CODE>/etc/rc.d</CODE> directory) scripts, so when you reboot your machine user's server will be
  +correctly shutdowned and will be back online the moment your system comes
  +back online. Also make sure to start each server under username the server
  +belongs to, if you are not looking for a big trouble.
  +
  +<P><LI>
   <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.
  +Proxy (in a forward or httpd accelerator mode) services for user's virtual
  +host. Since user will have to run her server on unprivileged port
  +(&gt;1024), you will have to forward all requests from
  +<CODE>user.given.virtual.hostname:80</CODE> (which is
  +<CODE>user.given.virtual.hostname</CODE> without port - 80 is a default) to
  +<CODE>your.machine.ip:port_assigned_to_user</CODE> and user to code his scripts to write self referencing URLs to be of <CODE>user.given.virtual.hostname</CODE>
  +base of course.
   
   <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.
  +Letting user to run a mod_perl server, immediately adds a requirement for
  +user to be able to restart and configure their own server. But only root
  +can bind port 80. That is why user has to use ports numbers &gt;1024.
   
  +<P><LI>
   <P>
  -Crontab entry:
  +Another problem you will have to solve is how to assign ports between
  +users. Since user can pick any port above 1024 to run his server on, you
  +will have to make some regulation here. A simple example will stress the
  +importance of this problem: I am a malicious user or I just a rival of some
  +fellow who runs his own server on your ISP. All I should do is to find out
  +what port his server is listening to (e.g. with help of <CODE>netstat(8)</CODE>) and configure my own server to listen on the same port. While I am unable
  +to bind to this same port, imagine what will happen when you reboot your
  +system and my startup script happen to be run before my rivals! I get the
  +port first, now all requests will be redirected to my server and let your
  +imagination go wild about what nasty things might happen then. Of course
  +the ugly things will be revealed pretty soon, but the damage has been done.
   
  +</UL>
  +<P><LI>
   <P>
  -<PRE>  0,30 * * * * /path/to/the/apache.watchdog &gt;/dev/null 2&gt;&amp;1
  -</PRE>
  +A much better, but costly solution is <STRONG>co-location</STRONG>. Let user to hook her (or ISP's) stand alone machine into your network,
  +and forget about this user. Of course either user or you will have to make
  +all the system administration chores and it will cost your client more
  +money.
  +
   <P>
  -The script:
  +All in all, who are the people who seek the mod_perl support? The ones who
  +run serious projects/businesses, who can afford a stand alone box, thus
  +gaining their goal of self autonomy and keeping their ISP happy. So money
  +is not an obstacle.
   
  +</OL>
   <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
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Virtual_Hosts_in_the_guide">Virtual Hosts in the guide</A></H1></CENTER>
  +<P>
  +If you are about to use <STRONG>Virtual Hosts</STRONG> you might want to read these sections:
  +
   <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.
  +<A HREF="././config.html#Perl_Sections">Perl Sections</A>.
   
   <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.
  +<A HREF="././config.html#Configuring_Apache_mod_perl_wi">Easing the chores of configuring the virtual hosts with mod_macro</A>
   
  +
  +
   <P>
  -So we end up with crontab entry:
  +<A HREF="././config.html#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>
   
  +
  +
   <P>
  -<PRE>  * * * * * /path/to/the/watchdog.pl &gt;/dev/null 2&gt;&amp;1
  -</PRE>
  +<A HREF="././config.html#Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host basis</A>
  +
  +
  +
   <P>
  -And the watchdog itself:
  +<A HREF="././config.html#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>
  +
  +
  +
  +<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="dbm.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="status.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 04/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: mod_perl Status. Peeking into the Server's Perl Innards</TITLE>
  +   <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
  +   <META NAME="Author" CONTENT="Bekman Stas">
  +   <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>
  +mod_perl Status. Peeking into the Server's Perl Innards</H1>
  +<HR WIDTH="100%">
  +	    [    <A HREF="multiuser.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="debug.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  +<UL>
  +
  +	<LI><A HREF="#Watching_the_server">Watching the server</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>
  +
  +</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>
  -<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>
  +<CENTER><H1><A NAME="Watching_the_server">Watching the server</A></H1></CENTER>
  +<P>
  +Very useful feature. You can watch what happens to the perl parts 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><H1><A NAME="Running_server_in_a_single_mode">Running server in a single mode</A></H1></CENTER>
  +<CENTER><H2><A NAME="Configuration">Configuration</A></H2></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_Not">Sometimes it works Sometimes 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.
  +Add this to http.conf:
   
   <P>
  -<PRE>  % /usr/apps/sbin/httpd_perl/httpd_perl -X
  +<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>
  -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.
  +If you are going to use Apache::Status. It's important to put it as a first
  +module in the start-up file, or in the httpd.conf. 
   
   <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>  # startup.pl
  +  use Apache::Registry ();
  +  use Apache::Status ();
  +  use Apache::DBI ();
  +</PRE>
  +<P>
  +If you don't put Apache::Status before Apache::DBI then you don't get
  +Apache::DBI's menu entry in status.
   
   <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.
  +For more about Apache::DBI 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><H1><A NAME="Starting_a_personal_server_for_e">Starting a personal server for each developer</A></H1></CENTER>
  +<CENTER><H2><A NAME="Usage">Usage</A></H2></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:
  +Assuming that your mod_perl server listens to port 81, fetch <A
  +HREF="http://www.myserver.com:81/perl-status">http://www.myserver.com:81/perl-status</A>
  +
   
   <P>
  -<PRE>  httpd_perl -f /path/to/httpd.conf  
  +<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>
  -I have approached it in other way. I have used the -Dparameter startup
  -option of the server. I call my version of the server
  +Below all sections should be links:
   
   <P>
  -<PRE>  % http_perl -Dsbekman
  +<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>
  -In <CODE>httpd.conf</CODE> I wrote:
  +Let's follow for example : PerlRequire'd Files =&gt; we see:
   
   <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>  PerlRequire                          Location
  +  /usr/apps/pais/lib/apache-startup.pl /usr/apps/pais/lib/apache-startup.pl
   </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''.
  +From some menus you can continue dipper to peek into internals of the
  +server, to see the values of the global variables in the packages, to the
  +the cached scripts and modules and much more. Just click around...
   
   <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:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Compiled_Registry_Scripts_sectio">Compiled Registry Scripts section seems to be empty.</A></H2></CENTER>
  +<P>
  +Sometimes when you fetch /perl-status you and follow the <STRONG>Compiled
  +Registry Scripts</STRONG> -- you see no listing of scripts at all. This is absolutely correct --
  +Apache::Status shows the registry scripts compiled in the httpd child which
  +is serving your request for /perl-status. If a child has not compiled yet
  +the script you are asking for, /perl-status will just show you the main
  +menu.
  +
  +<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="multiuser.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="debug.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 04/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: Debugging mod_perl</TITLE>
  +   <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
  +   <META NAME="Author" CONTENT="Bekman Stas">
  +   <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>
  +Debugging mod_perl</H1>
  +<HR WIDTH="100%">
  +	    [    <A HREF="status.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="browserbugs.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +<P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  +<UL>
  +
  +	<LI><A HREF="#Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A>
  +	<LI><A HREF="#Non_interactive_debugging_when_r">Non-interactive debugging when running under mod_perl</A>
  +	<LI><A HREF="#Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A>
  +	<LI><A HREF="#Debug_Tracing">Debug Tracing</A>
  +	<LI><A HREF="#gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A>
  +	<LI><A HREF="#Monitoring_error_log_file">Monitoring error_log file</A>
  +	<LI><A HREF="#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
  +	<LI><A HREF="#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
  +	<LI><A HREF="#Devel_Peek">Devel::Peek</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>
  -<PRE>  PIDFILE=/usr/apps/var/httpd_perl/run/httpd.pid.sbekman
  -  HTTPD='/usr/apps/sbin/httpd_perl/httpd_perl -Dsbekman'
  -</PRE>
  +<CENTER><H1><A NAME="Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A></H1></CENTER>
   <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.
  +See <A HREF="././porting.html#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it does Not</A>
  +
   
  +
   <P>
  -The last thing was to let developers an option to run in single process
  -mode by:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Non_interactive_debugging_when_r">Non-interactive debugging when running under mod_perl</A></H1></CENTER>
  +<P>
  +To debug scripts running under mod_perl either use <A HREF="././debug.html#Apache_DB_Run_the_interactive">Apache::DB (interactive Perl debugging)</A> or an older non-interactive method as described below.
   
   <P>
  -<PRE>  /usr/apps/sbin/httpd_perl/httpd_perl -Dsbekman -X
  +<CODE>NonStop</CODE> debugger option enables us to get some decent debug info when running under
  +mod_perl. For example, before starting the server:
  +
  +<P>
  +<PRE>  % setenv PERL5OPT -d
  +  % setenv PERLDB_OPTS &quot;NonStop=1 LineInfo=db.out AutoTrace=1 frame=2&quot;
   </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:
  +Now watch db.out for line:filename info. This is most useful for tracking
  +those core dumps that normally leave us guessing, even with a stack trace
  +from gdb. db.out will show you what Perl code triggered the core. 'man
  +perldebug' for more PERLDB_OPTS. Note, Perl will ignore PERL5OPT if <CODE>PerlTaintCheck</CODE> is <CODE>On</CODE>.
   
   <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="Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A></H1></CENTER>
  +<P>
  +Perl ships with a very useful interactive debugger, however, it does not
  +run ``out-of-the-box'' in the Apache/mod_perl environment.
  +<CODE>Apache::DB</CODE> makes a few adjustments so the two will cooperate.
   
   <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]
  +To configure it use:
  +
  +<P>
  +<PRE>  &lt;Location /perl&gt;
  +  PerlFixupHandler +Apache::DB
     
  +  SetHandler perl-script
  +  PerlHandler +Apache::Registry
  +  Options +ExecCGI
  +  &lt;/Location&gt;
   </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)
  +You must run the server in the single mode (with -X) to use
  +<CODE>Apache::DB</CODE>.
  +
  +<P>
  +When you run the script for the first time, you should let it run until it
  +finishes. Starting from the second run you can run it as if it was a
  +regular perl script.
  +
  +<P>
  +Module and Scripts that were preloaded and compiled during the server
  +startup will be not debuggable.
   
   <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>
  -
  +The filename and lines of Apache::Registry scripts are not displayed.
   
   <P>
  -Of course you have another problem: The cgi generates some html, which
  -should be called again. If it generates a URL with hard coded PORT the
  -above scheme will not work. There 2 solutions:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Debug_Tracing">Debug Tracing</A></H1></CENTER>
  +<P>
  +To enable mod_perl debug tracing configure mod_perl with the PERL_TRACE
  +option:
   
   <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!).
  +<PRE> perl Makefile.PL PERL_TRACE=1
  +</PRE>
  +<P>
  +The trace levels can then be enabled via the <CODE>MOD_PERL_TRACE</CODE>
  +environment variable which can contain any combination of:
   
   <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.
  +<PRE>  d - Trace directive handling during configuration read
  +  s - Trace processing of perl sections
  +  h - Trace Perl*Handler callbacks
  +  g - Trace global variable handling, interpreter construction, END blocks, etc.
  +  all - all of the above
  +</PRE>
  +<P>
  +add to httpd.conf:
   
   <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.
  +PerlSetVar MOD_PERL_TRACE all
   
   <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>
  +For example if you want to see a trace of the PerlRequire's and
  +PerlModule's as they are loaded, use:
  +
   <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.
  +PerlSetVar MOD_PERL_TRACE d
   
   <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.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A></H1></CENTER>
  +<P>
  +As you know you need an unstriped executable to be able to debug it. While
  +you can compile the mod_perl with <CODE>-g</CODE> (or <CODE>PERL_DEBUG=1</CODE>) the apache <CODE>install</CODE> strips the symbols.
   
   <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)
  +Makefile.tmpl contains a line:
   
   <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>  IFLAGS_PROGRAM  = -m 755 -s 
   </PRE>
   <P>
  +Removing the -s does the trick.
  +
  +<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>
  +<CENTER><H1><A NAME="Monitoring_error_log_file">Monitoring error_log file</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...
  +As I have mentioned it before, <CODE>error_log</CODE> file is your best friend in CGI code debugging process. 
   
   <P>
  -To rotate the logs do:
  +While debugging my mod_perl and general CGI code, I keep my
  +<CODE>error_log</CODE> file open in a dedicated terminal window (xterm), so I can see what
  +errors/warnings are being reported by server right away. I do it with:
   
   <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>  tail -f /usr/local/apache/logs/error_log
   </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>
  +which shows all the lines that are being added to the file.
  +
  +<P>
  +If you cannot access your <CODE>error_log</CODE> file because you are unable to telnet to your machine (generally a case
  +with some ISPs who provides user CGI support but no telnet access), you
  +might want to use a CGI script I wrote to fetch the latest lines from the
  +file (with a bonus of colored output for an easier reading). You might need
  +to ask your ISP to install this script for a general usage. See <A HREF="././snippets.html#Watching_the_error_log_file_with">Watching the error_log file without telneting to the server.</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><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A></H1></CENTER>
  +<P>
  +Current perl implementation does not restore the original apache's C
  +handler when you use <CODE>local $SIG{FOO}</CODE> clause. While save/restore of
  +<CODE>$SIG{ALRM}</CODE> was fixed in the mod_perl 1.19_01 (CVS version) other signals are not yet
  +fixed. The real fix should probably be in Perl itself.
   
   <P>
  -I use this script:
  +Untill recent <CODE>local $SIG{ALRM}</CODE> restored the <CODE>SIGALRM</CODE> handler to Perl's handler, not the handler it was in the first place
  +(apache's
  +<CODE>alrm_handler()</CODE>). if you build mod_perl with <CODE>PERL_TRACE=1</CODE> and set the <CODE>MOD_PERL_TRACE</CODE> environment variable to <STRONG>g</STRONG>, you will see this in the <CODE>error_log</CODE> file:
   
   <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>  mod_perl: saving SIGALRM (14) handler 0x80b1ff0
  +  mod_perl: restoring SIGALRM (14) handler from: 0x0 to: 0x80b1ff0
   </PRE>
   <P>
  -Randal L. Schwartz contributed this:
  +If nobody touched <CODE>$SIG{ALRM}</CODE>, <CODE>0x0</CODE> would be the same address as the others.
   
  -<BLOCKQUOTE>
  +<P>
  +If you work with signal handlers take a look at <CODE>Sys::Signal</CODE> module, which solves the problem:
   
   <P>
  -Cron fires off setuid script called log-roller that looks like this:
  +<CODE>Sys::Signal</CODE> - Set signal handlers with restoration of existing C sighandler. Get it
  +from the CPAN.
   
   <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;;
  +The usage is simple, if the original code was:
  +
  +<P>
  +<PRE>  eval {
  +    local $SIG{ALRM} = sub { die &quot;timeout\n&quot; };
  +    alarm $timeout;
  +    ... db stuff ...
  +    alarm 0;
  +  };
  +   
  +  die $@ if $@;
   </PRE>
   <P>
  -And then individual MIDNIGHT scripts can look like this:
  +Now you would write:
   
   <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>  use Sys::Signal ();
  +  eval {
  +    my $h = Sys::Signal-&gt;set(ALRM =&gt; sub { die &quot;timeout\n&quot; });
  +    alarm $timeout;
  +    ... do something thay may timeout ...
  +      alarm 0;
  +  };
  +  die $@ if $@;
   </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.
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="examples_of_strace_or_truss_us">examples of strace (or truss) usage</A></H1></CENTER>
  +<P>
  +(META: below are some snippets of strace outputs from list's emails)
   
  -</BLOCKQUOTE>
  +<P>
  +[there was a talk about Streaming LWP through mod_perl and the topic was
  +suggested optimal buffer size]
   
   <P>
  +Optimal buffer size depends on your system configuration, watch apache with <CODE>strace -p</CODE> (or <CODE>truss</CODE>) when its sending a static file, here perlfunc.pod on my laptop (linux
  +2.2.7):
  +
  +<P>
  +<PRE>  writev(4, [{&quot;HTTP/1.1 200 OK\r\nDate: Wed, 02&quot;..., 289}, {&quot;=head1
  +  NAME\n\nperlfunc - Perl b&quot;..., 32768}], 2) = 33057
  +  alarm(300)                              = 300
  +  write(4, &quot;m.  In older versions of Perl, i&quot;..., 32768) = 32768
  +  alarm(300)                              = 300
  +  write(4, &quot;hout waiting for the user to hit&quot;..., 32768) = 32768
  +  alarm(300)                              = 300
  +  write(4, &quot;&gt;&amp;STDOUT&quot;) || die &quot;Can't dup &quot;..., 32768) = 32768
  +  alarm(300)                              = 300
  +  write(4, &quot;LEHANDLE is supplied.  This has &quot;..., 32768) = 32768
  +  alarm(300)                              = 300
  +  write(4, &quot;ite&gt;,\nC&lt;seek&gt;, C&lt;tell&gt;, or C&lt;eo&quot;..., 25657) = 25657
  +</PRE>
  +<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 to eat up all the disk's space, when it goes wild.</A></H1></CENTER>
  +<CENTER><H1><A NAME="Devel_Peek">Devel::Peek</A></H1></CENTER>
   <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:
  +Devel::Peek - A data debugging tool for the XS programmer
   
   <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
  +Let's see an example of Perl allocating buffer size only once, regardless
  +of <CODE>my()</CODE> scoping, although it will realloc if the size is &gt;
  +SvLEN:
  +
  +<P>
  +<PRE>  use Devel::Peek;
  +  
  +  for (1..3) {
  +      foo();
  +  }
  +  
  +  sub foo {
  +      my $sv;
  +      Dump $sv;
  +      $sv = 'x' x 100_000;
  +      $sv = &quot;&quot;;
  +  }
   </PRE>
   <P>
  -It seems that his script will trigger restart every minute, since once the
  -logfile grows to be of 100000 lines, it will stay of this size, unless you
  -remove or rename it, before you do restart. On my server I run a watchdog
  -every five minutes which restarts the server if it is getting stuck (it
  -always works since when some modperl child process goes wild, the I/O it
  -causes is so heavy that other brother processes cannot normally to serve
  -the requests.) See <A HREF="././control.html#Monitoring_the_Server_A_watchdo">Monitoring the Server</A> for more hints.
  +The output:
   
   <P>
  -Also check out the daemontools from <A
  -HREF="ftp://koobera.math.uic.edu/www/daemontools.html">ftp://koobera.math.uic.edu/www/daemontools.html</A>
  +<PRE>  SV = NULL(0x0) at 0x8138008
  +    REFCNT = 1
  +    FLAGS = (PADBUSY,PADMY)
  +  SV = PV(0x80e5794) at 0x8138008
  +    REFCNT = 1
  +    FLAGS = (PADBUSY,PADMY)
  +    PV = 0x815f808 &quot;&quot;\0
  +    CUR = 0
  +    LEN = 100001
  +  SV = PV(0x80e5794) at 0x8138008
  +    REFCNT = 1
  +    FLAGS = (PADBUSY,PADMY)
  +    PV = 0x815f808 &quot;&quot;\0
  +    CUR = 0
  +</PRE>
  +<P>
  +We can see that on subsequent calls (after the first one) <CODE>$sv</CODE>
  +already has a preallocated memory.
   
  +<P>
  +so, if you can afford the memory, the larger the buffer means less
  +<CODE>brk()</CODE> syscalls. if you watch that example with strace, you will only see calls to <CODE>brk()</CODE> in the first time through the loop. So, this is a case where you module
  +might want to pre-allocate the buffer for example for LWP, a file scope
  +lexical, like so:
   
   <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>  package Your::Proxy;
  +  
  +  my $buffer = ' ' x 100_000;
  +  $buffer = &quot;&quot;;
   </PRE>
  +<P>
  +This way, only the parent has to <CODE>brk()</CODE> at server startup, each
  +child already will already have an allocated buffer, just reset to ``'',
  +when you are done.
  +
   <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>
  @@ -12567,7 +12966,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="multiuser.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="status.html">Next</A>      ]
  +	     [    <A HREF="status.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="browserbugs.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -12580,7 +12979,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/05/1999
         </FONT>
       </B>
     </TD>
  @@ -12607,7 +13006,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: mod_perl Status. Peeking into the Server's Perl Innards</TITLE>
  +   <TITLE>mod_perl guide: Workarounds for some known bugs in browsers.</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -12629,20 +13028,14 @@
   <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>
  -mod_perl Status. Peeking into the Server's Perl Innards</H1>
  +Workarounds for some known bugs in browsers.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="debug.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="debug.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="modules.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#Watching_the_server">Watching the server</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="#Preventing_QUERY_STRING_from_get">Preventing QUERY_STRING from getting corrupted because of &amp;entity key names.</A>
  +	<LI><A HREF="#IE_4_x_does_not_re_post_data_to_">IE 4.x does not re-post data to a non-port-80 URL</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -12659,95 +13052,33 @@
   	     <HR>
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<P>
  -<CENTER><H1><A NAME="Watching_the_server">Watching the server</A></H1></CENTER>
  -<P>
  -Very useful feature. You can watch what happens to the perl parts 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="Configuration">Configuration</A></H2></CENTER>
  -<P>
  -Add this to http.conf:
  -
  -<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 Apache::Status. It's important to put it as a first
  -module in the start-up file, or in the httpd.conf. 
  -
  -<P>
  -<PRE>  # startup.pl
  -  use Apache::Registry ();
  -  use Apache::Status ();
  -  use Apache::DBI ();
  -</PRE>
  +<CENTER><H1><A NAME="Preventing_QUERY_STRING_from_get">Preventing QUERY_STRING from getting corrupted because of &amp;entity key names.</A></H1></CENTER>
   <P>
  -If you don't put Apache::Status before Apache::DBI then you don't get
  -Apache::DBI's menu entry in status.
  +In URL <CODE>http://my.site.com/foo.pl?foo=bar&amp;reg=foobar</CODE> , some browsers will interpret <CODE>&amp;reg</CODE> as a magic entity, and encode it as it was
  +<CODE>&amp;reg;</CODE>, which will result in a corrupted <CODE>QUERY_STRING</CODE>. If you encounter this problem you should either avoid using such a keys
  +or separate parameter pairs with <CODE>;</CODE> instead of <CODE>&amp;</CODE>. Both <CODE>CGI.pm</CODE> and
  +<CODE>Apache::Request</CODE> support a semicolon instead of an ampersand as a separator. So your URI
  +should look like:
  +<CODE>http://my.site.com/foo.pl?foo=bar;reg=foobar</CODE>.
   
   <P>
  -For more about Apache::DBI see <A HREF="././performance.html#Persistent_DB_Connections">Persistent DB Connections</A>.
  +Note that this is only an issue when you are building your own URLs with
  +query strings, it is not a problem when the URL is the result of submitting
  +a form because the browsers _have_ to get that right.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Usage">Usage</A></H2></CENTER>
  -<P>
  -Assuming that your mod_perl server listens to port 81, fetch <A
  -HREF="http://www.myserver.com:81/perl-status">http://www.myserver.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>
  +<CENTER><H1><A NAME="IE_4_x_does_not_re_post_data_to_">IE 4.x does not re-post data to a non-port-80 URL</A></H1></CENTER>
   <P>
  -Below all sections should be links:
  +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>  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 : PerlRequire'd Files =&gt; we see:
  +See <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>
   
  -<P>
  -<PRE>  PerlRequire                          Location
  -  /usr/apps/pais/lib/apache-startup.pl /usr/apps/pais/lib/apache-startup.pl
  -</PRE>
  -<P>
  -From some menus you can continue dipper to peek into internals of the
  -server, to see the values of the global variables in the packages, to the
  -the 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><H2><A NAME="Compiled_Registry_Scripts_sectio">Compiled Registry Scripts section seems to be empty.</A></H2></CENTER>
  -<P>
  -Sometimes when you fetch /perl-status you and follow the <STRONG>Compiled
  -Registry Scripts</STRONG> -- you see no listing of scripts at all. This is absolutely correct --
  -Apache::Status shows the registry scripts compiled in the httpd child which
  -is serving your request for /perl-status. If a child has not compiled yet
  -the script you are asking for, /perl-status will just show you the main
  -menu.
   
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -12759,7 +13090,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="debug.html">Next</A>      ]
  +	     [    <A HREF="debug.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="modules.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -12772,7 +13103,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 05/15/1999
         </FONT>
       </B>
     </TD>
  @@ -12799,7 +13130,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Debugging mod_perl</TITLE>
  +   <TITLE>mod_perl guide: Apache::* modules</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -12821,144 +13152,260 @@
   <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>
  -Debugging mod_perl</H1>
  +Apache::* modules</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="status.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="browserbugs.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="browserbugs.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="perl.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#Sometimes_script_works_Sometime">Sometimes script works, Sometimes Not</A>
  -	<LI><A HREF="#Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A>
  -	<LI><A HREF="#Debug_Tracing">Debug Tracing</A>
  -	<LI><A HREF="#Getting_some_decent_debug_info_w">Getting some decent debug info when running under mod_perl</A>
  -	<LI><A HREF="#gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A>
  +	<LI><A HREF="#Apache_Session_Maintain_sessi">Apache::Session - Maintain session state across HTTP requests</A>
  +	<LI><A HREF="#Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A>
  +	<LI><A HREF="#Apache_Request_libapreq_Gen">Apache::Request (libapreq) - Generic Apache Request Library</A>
  +	<LI><A HREF="#Apache_PerlRun_Run_unaltered_">Apache::PerlRun - Run unaltered CGI scripts under mod_perl</A>
  +	<LI><A HREF="#Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A>
  +	<LI><A HREF="#Apache_PerlVINC_set_a_differe">Apache::PerlVINC - set a different @INC perl-location </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="Apache_Session_Maintain_sessi">Apache::Session - Maintain session state across HTTP requests</A></H1></CENTER>
  +<P>
  +This module provides the Apache/mod_perl user a mechanism for storing
  +persistent user data in a global hash, which is independent of its real
  +storage mechanism. Currently you can choose from these storage mechanisms <CODE>Apache::Session::DBI</CODE>, <CODE>Apache::Session::Win32</CODE>,
  +<CODE>Apache::Session::File</CODE>, <CODE>Apache::Session::IPC</CODE>. Read the man page of the mechanism you want to use for a complete
  +reference.
  +
  +<P>
  +What Apache::Session does is provide persistence to a data structure. The
  +data structure has an ID number, and you can retrieve it by using the ID
  +number. In the case of Apache, you would store the ID number in a cookie or
  +the URL to associate it with one browser, but the method of dealing with
  +the ID is completely up to you. The flow of things is generally:
  +
  +<P>
  +<PRE>  Tie a session to Apache::Session.
  +  Get the ID number.
  +  Store the ID number in a cookie.
  +  End of Request 1.
  +</PRE>
  +<P>
  +<PRE>  (time passes)
  +</PRE>
  +<P>
  +<PRE>  Get the cookie.
  +  Restore your hash using the ID number in the cookie.
  +  Use whatever data you put in the hash.
  +  End of Request 2.
  +</PRE>
  +<P>
  +Using Apache::Session is easy: simply tie a hash to the session object,
  +stick any data structure into the hash, and the data you put in
  +automatically persists until the next invocation. Here is a quick example
  +which uses cookies to track the user's session.
  +
  +<P>
  +<PRE>  #  Pull in the require packages
  +  use Apache::Session::DBI;
  +  use Apache;
  +  
  +  use strict;
  +  
  +  # Read in the cookie if this is an old session
  +  my $r = Apache-&gt;request;
  +  my $cookie = $r-&gt;header_in('Cookie');
  +  $cookie =~ s/SESSION_ID=(\w*)/$1/;
  +  
  +  # Create a session object based on the cookie we got from the
  +  # browser, or a new session if we got no cookie
  +  my %session;
  +  tie %session, 'Apache::Session::DBI', $cookie,
  +      {DataSource =&gt; 'dbi:mysql:sessions',
  +       UserName   =&gt; $db_user,
  +       Password   =&gt; $db_pass
  +      };
  +  
  +  # Might be a new session, so lets give them their cookie back
  +  my $session_cookie = &quot;SESSION_ID=$session{_session_id};&quot;;
  +  $r-&gt;header_out(&quot;Set-Cookie&quot; =&gt; $session_cookie);
  +</PRE>
  +<P>
  +After setting this up, you can stick anything you want into
  +<CODE>%session</CODE> (except file handles), and it will still be there
  +when the user invokes the next page.
   
  -<HR>
  +<P>
  +It is possible to write an Apache authen handler using Apache::Session. You
  +can put your authentication token into the session. When a user invokes a
  +page, you open their session, check to see if they have a valid token, and
  +approve or deny their authorization based on that.
   
  -	     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>
  +As for IIS, let's compare. IIS's sessions are only valid on the same web
  +server as the one that issued the session. Apache::Session's session
  +objects can be shared amongst a farm of many machines running different
  +operating systems, including even Win32. IIS stores session information in
  +RAM. Apache::Session stores sessions in databases, file systems, or RAM.
  +IIS's sessions are only good for storing scalars or arrays.
  +Apache::Session's sessions allow you to store arbitrarily complex objects.
  +IIS sets up the session and automatically tracks it for you. With
  +Apache::Session, you setup and track the session yourself. IIS is
  +proprietary. Apache::Session is open-source. Apache::Session::DBI can issue
  +400+ session requests per second on light Celeron 300A running Linux. IIS?
   
  -	     <HR>
  +<P>
  +An alternative to Apache::Session is Apache::ASP, which has session
  +tracking abilities. HTML::Embperl hooks into Apache::Session for you.
   
  -	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Sometimes_script_works_Sometime">Sometimes script works, Sometimes Not</A></H1></CENTER>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A></H1></CENTER>
   <P>
  -See <A HREF="././porting.html#Sometimes_it_Works_Sometimes_Not">Sometimes it works Sometimes Not</A>
  +See <A HREF="././databases.html#Apache_DBI_Initiate_a_persist">mod_perl and relational Databases</A>
   
   
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A></H1></CENTER>
  +<CENTER><H1><A NAME="Apache_Request_libapreq_Gen">Apache::Request (libapreq) - Generic Apache Request Library</A></H1></CENTER>
   <P>
  -Perl ships with a very useful interactive debugger, however, it does not
  -run ``out-of-the-box'' in the Apache/mod_perl environment. Apache::DB makes
  -a few adjustments so the two will cooperate.
  +This package contains modules for manipulating client request data via the
  +Apache API with Perl and C. Functionality includes:
   
   <P>
  -To configure it use:
  +- parsing of application/x-www-form-urlencoded data
   
   <P>
  -<PRE>  &lt;Location /perl&gt;
  -  PerlFixupHandler +Apache::DB
  -  
  -  SetHandler perl-script
  -  PerlHandler +Apache::Registry
  -  Options +ExecCGI
  -  &lt;/Location&gt;
  -</PRE>
  +- parsing of multipart/form-data
  +
   <P>
  -You must run the server in the single mode (with -X) to use Apache::DB.
  +- parsing of HTTP Cookies
   
   <P>
  -When you run the script for the first time, you should let it run until it
  -finishes. Starting from the second run you can run it as if it was a
  -regular perl script. 
  +The Perl modules are simply a thin xs layer on top of libapreq, making them
  +a lighter and faster alternative to CGI.pm and CGI::Cookie. See the
  +Apache::Request and Apache::Cookie documentation for more details and
  +eg/perl/ for examples.
   
   <P>
  -Module and Scripts that were preloaded and compiled during the server
  -startup will be not debuggable.
  +Apache::Request and the libapreq are tied tight to the Apache API, which
  +there is no access to in a process running under mod_cgi.
   
   <P>
  -The filename and lines of Apache::Registry scripts are not displayed.
  +Get it from CPAN at $CPAN/authors/id/DOUGM/libapreq-x.xx.tar.gz or from <A
  +HREF="http://perl.apache.org/dist/libapreq-x.xx.tar.gz">http://perl.apache.org/dist/libapreq-x.xx.tar.gz</A>
  +. (replace x.xx with the current version)
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Debug_Tracing">Debug Tracing</A></H1></CENTER>
  +<CENTER><H1><A NAME="Apache_PerlRun_Run_unaltered_">Apache::PerlRun - Run unaltered CGI scripts under mod_perl</A></H1></CENTER>
   <P>
  -To enable mod_perl debug tracing configure mod_perl with the PERL_TRACE
  -option:
  +See <A HREF="././porting.html#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>.
   
   <P>
  -<PRE> perl Makefile.PL PERL_TRACE=1
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A></H1></CENTER>
   <P>
  -The trace levels can then be enabled via the <CODE>MOD_PERL_TRACE</CODE>
  -environment variable which can contain any combination of:
  +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.
   
   <P>
  -<PRE>  d - Trace directive handling during configuration read
  -  s - Trace processing of perl sections
  -  h - Trace Perl*Handler callbacks
  -  g - Trace global variable handling, interpreter construction, END blocks, etc.
  -  all - all of the above
  +<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.
  +
  +<P>
  +For example to compress all html files on the fly, do:
  +
  +<P>
  +<PRE>  &lt;Files *.html&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::OutputChain Apache::GzipChain Apache::PassFile
  +  &lt;/Files&gt;
   </PRE>
   <P>
  -add to httpd.conf:
  +Remember that it will work only if the browsers 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.
   
   <P>
  -PerlSetVar MOD_PERL_TRACE all
  +For example if you want to return compressed files which should pass in
  +addition through Embperl module, you would write:
   
   <P>
  -For example if you want to see a trace of the PerlRequire's and
  -PerlModule's as they are loaded, use:
  +<PRE>  &lt;Location /test&gt;
  +    SetHandler &quot;perl-script&quot;
  +    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.
   
   <P>
  -PerlSetVar MOD_PERL_TRACE d
  +See the module's documentaion for more details.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Getting_some_decent_debug_info_w">Getting some decent debug info when running under mod_perl</A></H1></CENTER>
  +<CENTER><H1><A NAME="Apache_PerlVINC_set_a_differe">Apache::PerlVINC - set a different @INC perl-location</A></H1></CENTER>
   <P>
  -As many of you know, the interactive Perl debugger does not run under
  -Apache/mod_perl (yet). However, Dean Gaudet made the discovery last night
  -of the NonStop option. This enables us to get some decent debug info when
  -running under mod_perl. For example, before starting the server:
  +With that module, you can configure <CODE>@INC</CODE> and have modules reloaded for a given <CODE>Location</CODE>, e.g. say two versions of <CODE>Apache::Status</CODE>
  +are being hacked on in the same server, this fixup handler will simply
  +<CODE>delete $INC{ $filename }</CODE>, unshift the prefered <CODE>PerlINC</CODE> path into
  +<CODE>@INC</CODE>, and reload the file with <CODE>require()</CODE>:
   
   <P>
  -<PRE>  % setenv PERL5OPT -d
  -  % setenv PERLDB_OPTS &quot;NonStop=1 LineInfo=db.out AutoTrace=1 frame=2&quot;
  +<PRE>  PerlModule Apache::PerlVINC
   </PRE>
   <P>
  -Now watch db.out for line:filename info. This is most useful for tracking
  -those core dumps that normally leave us guessing, even with a stack trace
  -from gdb. db.out will show you what Perl code triggered the core. 'man
  -perldebug' for more PERLDB_OPTS. Note, Perl will ignore PERL5OPT if <CODE>PerlTaintCheck</CODE> is <CODE>On</CODE>.
  -
  +<PRE>  &lt;Location /dougm-status&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Status
  +  
  +    PerlINC /home/dougm/dev/modperl/lib
  +    PerlVersionINC On
  +    PerlFixupHandler Apache::PerlVINC
  +    PerlRequire Apache/Status.pm
  +  &lt;/Location&gt;
  +</PRE>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A></H1></CENTER>
  +<PRE>  &lt;Location /other-status&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Status
  +  
  +    PerlINC /home/other/current/modperl/lib
  +    PerlVersionINC On
  +    PerlFixupHandler Apache::PerlVINC
  +    PerlRequire Apache/Status.pm
  +  &lt;/Location&gt;
  +</PRE>
   <P>
  -As you know you need an unstriped executable to be able to debug it. While
  -you can compile the mod_perl with <CODE>-g</CODE> the apache
  -<CODE>install</CODE> strips the symbols.
  +To address possible issues of namespace clashes during reload, the handler
  +could call $r-&gt;child_terminate() so the next server to load the
  +different versions will have a fresh namespace. (not a good idea in a high
  +load environment, of course.)
   
   <P>
  -Makefile.tmpl contains a line:
  +If it is still absent from CPAN get it at: <A
  +HREF="http://perl.apache.org/~dougm/Apache-PerlVINC-0.01.tar.gz">http://perl.apache.org/~dougm/Apache-PerlVINC-0.01.tar.gz</A>
   
  -<P>
  -<PRE>  IFLAGS_PROGRAM  = -m 755 -s 
  -</PRE>
  -<P>
  -Removing the -s does the trick.
   
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -12970,7 +13417,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="status.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="browserbugs.html">Next</A>      ]
  +	     [    <A HREF="browserbugs.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="perl.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -12983,7 +13430,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/05/1999
         </FONT>
       </B>
     </TD>
  @@ -13010,7 +13457,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Workarounds for some known bugs in browsers.</TITLE>
  +   <TITLE>mod_perl guide: Perl Reference</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -13032,14 +13479,22 @@
   <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>
  -Workarounds for some known bugs in browsers.</H1>
  +Perl Reference</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="debug.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="modules.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="modules.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="snippets.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#Preventing_QUERY_STRING_from_get">Preventing QUERY_STRING from getting corrupted because of &amp;entity key names.</A>
  -	<LI><A HREF="#IE_4_x_does_not_re_post_data_to_">IE 4.x does not re-post data to a non-port-80 URL</A>
  +	<LI><A HREF="#Coverage">Coverage</A>
  +	<LI><A HREF="#Using_global_variables_and_shari">Using global variables and sharing them between modules/packages</A>
  +	<UL>
  +
  +		<LI><A HREF="#Making_the_variables_global">Making the variables global</A>
  +		<LI><A HREF="#Making_the_variables_global_with">Making the variables global with strict pragma On</A>
  +		<LI><A HREF="#Using_Exporter_pm_to_share_globa">Using Exporter.pm to share global variables</A>
  +		<LI><A HREF="#Using_aliasing_perl_feature_to_s">Using aliasing perl feature to share global variables</A>
  +	</UL>
  +
   </UL>
   <!-- INDEX END -->
   
  @@ -13052,38 +13507,257 @@
   	     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="Coverage">Coverage</A></H1></CENTER>
  +<P>
  +This new document was born because some users reluctant to learn perl prior
  +to jumping into a mod_perl. I will try to cover some of the most frequent
  +pure perl questions being asked at the list.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Using_global_variables_and_shari">Using global variables and sharing them between modules/packages</A></H1></CENTER>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Making_the_variables_global">Making the variables global</A></H2></CENTER>
  +<P>
  +When you first wrote <CODE>$x</CODE> in your code you created a global
  +variable. It is visible everywhere in the file you have use it. or if
  +defined it inside a package - it is visible inside this package. But it
  +will work only if you do not use <CODE>strict</CODE> pragma and you <STRONG>HAVE</STRONG> to use this pragma if you want to run your scripts under mod_perl. Read <A HREF="././porting.html#strict_pragma">Strict pragma</A> to find out why.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Making_the_variables_global_with">Making the variables global with strict pragma On</A></H2></CENTER>
  +<P>
  +First you use :
  +
  +<P>
  +<PRE>  use strict;
  +</PRE>
  +<P>
  +Then you use:
  +
  +<P>
  +<PRE> use vars qw($scalar %hash @array);
  +</PRE>
  +<P>
  +Starting from this moment the variables are global in the package you
  +defined them, if you want to share global variables between packages, here
  +what you can do.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Using_Exporter_pm_to_share_globa">Using Exporter.pm to share global variables</A></H2></CENTER>
  +<P>
  +Assume that you want to share the <CODE>CGI.pm</CODE>'s object (I will use <CODE>$q</CODE>) between your modules. For example you create it in the <CODE>script.pl</CODE>, but want it to be visible in <CODE>My::HTML</CODE>. First - you make <CODE>$q</CODE> global.
  +
  +<P>
  +<PRE>  script.pl:
  +  ----------------
  +  use vars qw($q);
  +  use CGI;
  +  use lib qw(.); 
  +  use My::HTML qw($q); # My/HTML.pm in the same dir as script.pl
  +  $q = new CGI;
  +  
  +  My::HTML::printmyheader();
  +  ----------------
  +</PRE>
  +<P>
  +Note that we have imported <CODE>$q</CODE> from <CODE>My::HTML</CODE>. And the <CODE>My::HTML</CODE>
  +which does the export of <CODE>$q</CODE>:
  +
  +<P>
  +<PRE>  My/HTML.pm
  +  ----------------
  +  package My::HTML;
  +  use strict;
  +  
  +  BEGIN {
  +    use Exporter ();
  +  
  +    @My::HTML::ISA         = qw(Exporter);
  +    @My::HTML::EXPORT      = qw();
  +    @My::HTML::EXPORT_OK   = qw($q);
  +  
  +  }
  +  
  +  use vars qw($q);
  +  
  +  sub printmyheader{
  +    # Whatever you want to do with $q... e.g.
  +    print $q-&gt;header();
  +  }
  +  1;
  +  -------------------
  +</PRE>
  +<P>
  +So the <CODE>$q</CODE> is being shared between the <CODE>My::HTML</CODE> package and the
  +<CODE>script.pl</CODE>. It will work vice versa as well, if you create the object in the <CODE>My::HTML</CODE> but use it in the <CODE>script.pl</CODE>. You have a true sharing, since if you change <CODE>$q</CODE> in <CODE>script.pl</CODE>, it will be changed in <CODE>My::HTML</CODE> as well.
  +
  +<P>
  +What if you need to share <CODE>$q</CODE> between more than 2 packages? For example you want My::Doc to share <CODE>$q</CODE> as well.
   
  -	     <HR>
  +<P>
  +You leave the <CODE>My::HTML</CODE> untouched, modify the script.pl to include:
   
  -	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Preventing_QUERY_STRING_from_get">Preventing QUERY_STRING from getting corrupted because of &amp;entity key names.</A></H1></CENTER>
  +<PRE> use My::Doc qw($q);
  +</PRE>
   <P>
  -In URL <CODE>http://my.site.com/foo.pl?foo=bar&amp;reg=foobar</CODE> , some browsers will interpret <CODE>&amp;reg</CODE> as a magic entity, and encode it as it was
  -<CODE>&amp;reg;</CODE>, which will result in a corrupted <CODE>QUERY_STRING</CODE>. If you encounter this problem you should either avoid using such a keys
  -or separate parameter pairs with <CODE>;</CODE> instead of <CODE>&amp;</CODE>. Both <CODE>CGI.pm</CODE> and
  -<CODE>Apache::Request</CODE> support a semicolon instead of an ampersand as a separator. So your URI
  -should look like:
  -<CODE>http://my.site.com/foo.pl?foo=bar;reg=foobar</CODE>.
  +And write the <CODE>My::Doc</CODE> exactly like <CODE>My::HTML</CODE> - of course that the content is different :).
   
   <P>
  -Note that this is only an issue when you are building your own URLs with
  -query strings, it is not a problem when the URL is the result of submitting
  -a form because the browsers _have_ to get that right.
  +One possible pitfall is when you want to use the <CODE>My::Doc</CODE> in both
  +<CODE>My::HTML</CODE> and <CODE>script.pl</CODE>. Only if you add:
  +
  +<P>
  +<PRE>  use My::Doc qw($q);
  +</PRE>
  +<P>
  +Into a <CODE>My::HTML</CODE>, the <CODE>$q</CODE> will be shared. Otherwise <CODE>My::Doc</CODE> will not share the <CODE>$q</CODE> anymore. To make things clear here is the code:
   
   <P>
  +<PRE>  script.pl:
  +  ----------------
  +  use vars qw($q);
  +  use CGI;
  +  use lib qw(.); 
  +  use My::HTML qw($q); # My/HTML.pm in the same dir as script.pl
  +  use My::Doc  qw($q); # Ditto
  +  $q = new CGI;
  +  
  +  My::HTML::printmyheader();
  +  ----------------
  +</PRE>
  +<P>
  +<PRE>  My/HTML.pm
  +  ----------------
  +  package My::HTML;
  +  use strict;
  +  
  +  BEGIN {
  +    use Exporter ();
  +  
  +    @My::HTML::ISA         = qw(Exporter);
  +    @My::HTML::EXPORT      = qw();
  +    @My::HTML::EXPORT_OK   = qw($q);
  +  
  +  }
  +  
  +  use vars     qw($q);
  +  use My::Doc  qw($q);
  +  
  +  sub printmyheader{
  +    # Whatever you want to do with $q... e.g.
  +    print $q-&gt;header();
  +  
  +    My::Doc::printtitle('Guide');
  +  }
  +  1;
  +  -------------------
  +</PRE>
  +<P>
  +<PRE>  My/Doc.pm
  +  ----------------
  +  package My::Doc;
  +  use strict;
  +  
  +  BEGIN {
  +    use Exporter ();
  +  
  +    @My::Doc::ISA         = qw(Exporter);
  +    @My::Doc::EXPORT      = qw();
  +    @My::Doc::EXPORT_OK   = qw($q);
  +  
  +  }
  +  
  +  use vars qw($q);
  +  
  +  sub printtitle{
  +    my $title = shift || 'None';
  +    
  +    print $q-&gt;h1($title);
  +  }
  +  1;
  +  -------------------
  +</PRE>
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="IE_4_x_does_not_re_post_data_to_">IE 4.x does not re-post data to a non-port-80 URL</A></H1></CENTER>
  +<CENTER><H2><A NAME="Using_aliasing_perl_feature_to_s">Using aliasing perl feature to share global variables</A></H2></CENTER>
   <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.
  +As the title says you can import a variable into a script/module without
  +using an Exporter.pm. I have found it useful to keep all the configuration
  +variables in one module <CODE>My::Config</CODE>. But then I have to export all the variables in order to use them in other
  +modules, which is bad for two reasons: polluting other packages' name
  +spaces with extra tags which rise up the memory requirements, adding an
  +overhead of keeping track of what variables should be exported from the
  +configuration module and what imported for some particular package. I solve
  +this problem by keeping all the variables in one hash <CODE>%c</CODE> and exporting only it. Here is an example of <CODE>My::Config</CODE>:
   
   <P>
  -See <A HREF="././config.html#Publishing_port_numbers_differen">Publishing port numbers different from 80</A>
  +<PRE>  package My::Config;
  +  use strict;
  +  use vars qw(%c);
  +  %c = (
  +    # All the configs go here
  +    scalar_var =&gt; 5,
  +  
  +    array_var  =&gt; [
  +                   foo,
  +                   bar,
  +                  ],
  +  
  +    hash_var   =&gt; {
  +                   foo =&gt; 'Foo',
  +                   bar =&gt; 'BARRR',
  +                  },
  +  );
  +  1;
  +</PRE>
  +<P>
  +Now in packages that want to use the configuration variables I have either
  +to use the fully qualified names like <CODE>$My::Config::test</CODE>, which I dislike or import them as described in the previous section. But
  +hey, since we have only one variable to handle, we can make things even
  +simpler and save the loading of the <CODE>Exporter.pm</CODE> package. We will use aliasing perl feature for exporting and saving the
  +keystrokes:
  +
  +<P>
  +<PRE>  package My::HTML;
  +  use strict;
  +  use lib qw(.);
  +    # Global Configuration now aliased to global %c
  +  use My::Config (); # My/Config.pm in the same dir as script.pl
  +  use vars qw(%c);
  +  *c = \%My::Config::c;
  +  
  +    # Now you can access the variables from the My::Config
  +  print $c{scalar_val};
  +  print $c{array_val}[0];
  +  print $c{hash_val}{foo};
  +</PRE>
  +<P>
  +Of course <CODE>$c</CODE> is global everywhere you use it as described
  +above, and if you change it somewhere it will affect any other packages you
  +have aliased <CODE>$My::Config::c</CODE> to.
   
  +<P>
  +Note that aliases work either with global or <CODE>local()</CODE> vars - you cannot write:
   
  +<P>
  +<PRE>  my *c = \%My::Config::c;
  +</PRE>
  +<P>
  +Which is an error. But you can:
   
  +<P>
  +<PRE>  local *c = \%My::Config::c;
  +</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>
  @@ -13094,7 +13768,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="debug.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="modules.html">Next</A>      ]
  +	     [    <A HREF="modules.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="snippets.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -13107,7 +13781,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/15/1999
  +	     <BR>Last Modified at 06/05/1999
         </FONT>
       </B>
     </TD>
  @@ -13134,7 +13808,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Apache::* modules</TITLE>
  +   <TITLE>mod_perl guide: Code Snippets</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -13156,16 +13830,18 @@
   <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>
  -Apache::* modules</H1>
  +Code Snippets</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="browserbugs.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="perl.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="perl.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="hardware.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#Apache_Session_Maintain_sessi">Apache::Session - Maintain session state across HTTP requests</A>
  -	<LI><A HREF="#Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A>
  -	<LI><A HREF="#Apache_Request_libapreq_Gen">Apache::Request (libapreq) - Generic Apache Request Library</A>
  -	<LI><A HREF="#Apache_PerlRun_Run_unaltered_">Apache::PerlRun - Run unaltered CGI scripts under mod_perl</A>
  +	<LI><A HREF="#Sending_MIME_headers">Sending MIME headers</A>
  +	<LI><A HREF="#How_to_avoid_printing_the_header">How to avoid printing the header more than once.</A>
  +	<LI><A HREF="#More_on_relative_paths">More on relative paths</A>
  +	<LI><A HREF="#Watching_the_error_log_file_with">Watching the error_log file without telneting to the server.</A>
  +	<LI><A HREF="#Accessing_variables_from_the_cal">Accessing variables from the caller's package</A>
  +	<LI><A HREF="#Handling_cookies">Handling cookies</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -13182,141 +13858,204 @@
   	     <HR>
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<P>
  -<CENTER><H1><A NAME="Apache_Session_Maintain_sessi">Apache::Session - Maintain session state across HTTP requests</A></H1></CENTER>
  -<P>
  -This module provides the Apache/mod_perl user a mechanism for storing
  -persistent user data in a global hash, which is independent of its real
  -storage mechanism. Currently you can choose from these storage mechanisms <CODE>Apache::Session::DBI</CODE>, <CODE>Apache::Session::Win32</CODE>,
  -<CODE>Apache::Session::File</CODE>, <CODE>Apache::Session::IPC</CODE>. Read the man page of the mechanism you want to use for a complete
  -reference.
  -
  -<P>
  -What Apache::Session does is provide persistence to a data structure. The
  -data structure has an ID number, and you can retrieve it by using the ID
  -number. In the case of Apache, you would store the ID number in a cookie or
  -the URL to associate it with one browser, but the method of dealing with
  -the ID is completely up to you. The flow of things is generally:
  -
  -<P>
  -<PRE>  Tie a session to Apache::Session.
  -  Get the ID number.
  -  Store the ID number in a cookie.
  -  End of Request 1.
  -</PRE>
  -<P>
  -<PRE>  (time passes)
  -</PRE>
  -<P>
  -<PRE>  Get the cookie.
  -  Restore your hash using the ID number in the cookie.
  -  Use whatever data you put in the hash.
  -  End of Request 2.
  -</PRE>
  -<P>
  -Using Apache::Session is easy: simply tie a hash to the session object,
  -stick any data structure into the hash, and the data you put in
  -automatically persists until the next invocation. Here is a quick example
  -which uses cookies to track the user's session.
  -
  -<P>
  -<PRE>  #  Pull in the require packages
  -  use Apache::Session::DBI;
  -  use Apache;
  -  
  -  use strict;
  -  
  -  # Read in the cookie if this is an old session
  -  my $r = Apache-&gt;request;
  -  my $cookie = $r-&gt;header_in('Cookie');
  -  $cookie =~ s/SESSION_ID=(\w*)/$1/;
  -  
  -  # Create a session object based on the cookie we got from the
  -  # browser, or a new session if we got no cookie
  -  my %session;
  -  tie %session, 'Apache::Session::DBI', $cookie,
  -      {DataSource =&gt; 'dbi:mysql:sessions',
  -       UserName   =&gt; $db_user,
  -       Password   =&gt; $db_pass
  -      };
  -  
  -  # Might be a new session, so lets give them their cookie back
  -  my $session_cookie = &quot;SESSION_ID=$session{_session_id};&quot;;
  -  $r-&gt;header_out(&quot;Set-Cookie&quot; =&gt; $session_cookie);
  -</PRE>
  -<P>
  -After setting this up, you can stick anything you want into
  -<CODE>%session</CODE> (except file handles), and it will still be there
  -when the user invokes the next page.
  -
  -<P>
  -It is possible to write an Apache authen handler using Apache::Session. You
  -can put your authentication token into the session. When a user invokes a
  -page, you open their session, check to see if they have a valid token, and
  -approve or deny their authorization based on that.
  -
   <P>
  -As for IIS, let's compare. IIS's sessions are only valid on the same web
  -server as the one that issued the session. Apache::Session's session
  -objects can be shared amongst a farm of many machines running different
  -operating systems, including even Win32. IIS stores session information in
  -RAM. Apache::Session stores sessions in databases, file systems, or RAM.
  -IIS's sessions are only good for storing scalars or arrays.
  -Apache::Session's sessions allow you to store arbitrarily complex objects.
  -IIS sets up the session and automatically tracks it for you. With
  -Apache::Session, you setup and track the session yourself. IIS is
  -proprietary. Apache::Session is open-source. Apache::Session::DBI can issue
  -400+ session requests per second on light Celeron 300A running Linux. IIS?
  +<CENTER><H1><A NAME="Sending_MIME_headers">Sending MIME headers</A></H1></CENTER>
  +<P>
  +By default, mod_perl does not send any headers by itself, however, you may
  +wish to change this behavior by setting in config file: 
   
   <P>
  -An alternative to Apache::Session is Apache::ASP, which has session
  -tracking abilities. HTML::Embperl hooks into Apache::Session for you.
  +<PRE>  PerlSendHeader On
  +</PRE>
  +<P>
  +The safest bet is to use CGI.pm's <CODE>print header();</CODE> method (If you use this, you don't need the above setting)
  +
  +<P>
  +Also there is $ENV{PERL_SEND_HEADER} to see if PerlSendHeader is On or Off.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A></H1></CENTER>
  +<CENTER><H1><A NAME="How_to_avoid_printing_the_header">How to avoid printing the header more than once.</A></H1></CENTER>
   <P>
  -See <A HREF="././databases.html#Apache_DBI_Initiate_a_persist">mod_perl and relational Databases</A>
  -
  +I'm sure you have been in the situations, where you wish you knew whether
  +the MIME header has been already printed. Since if it was printing it again
  +will cause an ugly ``Content-type: ...'' string show up at the web page. So
  +how do we solve it? With help of closure.
   
  +<P>
  +Just copy the code below as it is, including the block's curly parentheses.
  +And everywhere in your code use the <CODE>print_header()</CODE> sub to
  +print the header. <CODE>$need_header</CODE> is the same beast as static variable in C, so it remembers its value from
  +call to call.
   
   <P>
  +<PRE>  {
  +    my $need_header = 1;
  +    sub print_header {
  +      print header(@_),$need_header = 0 if $need_header;
  +    }
  +  }
  +</PRE>
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Apache_Request_libapreq_Gen">Apache::Request (libapreq) - Generic Apache Request Library</A></H1></CENTER>
  +<CENTER><H1><A NAME="More_on_relative_paths">More on relative paths</A></H1></CENTER>
   <P>
  -This package contains modules for manipulating client request data via the
  -Apache API with Perl and C. Functionality includes:
  +Many use a relative require call, or write to the file in the current or
  +relative to the current directory. But this will fail if you wouldn't
  +<CODE>chdir()</CODE> into the directory first. So you have to either do
  +this in the code or to use a nice <CODE>FindBin.pm</CODE> package.
   
   <P>
  -- parsing of application/x-www-form-urlencoded data
  +<PRE>  use FindBin qw($Bin);
  +  use lib $Bin;
  +  # or
  +  open IN, &quot;$Bin/foo.txt&quot;;
  +</PRE>
  +<P>
  +Now <CODE>$Bin</CODE> includes the path of the directory the script resides on, so you can move
  +the script from one directory to the other and call it from anywhere else,
  +the paths will be always correct.
   
   <P>
  -- parsing of multipart/form-data
  +It's different from using the ``./foo'', for you have to chdir to the
  +directory the script located at first. (Think about crontabs!!!)
   
   <P>
  -- parsing of HTTP Cookies
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Watching_the_error_log_file_with">Watching the error_log file without telneting to the server.</A></H1></CENTER>
  +<P>
  +I wrote this script long time ago, when I have had to debug my cgi scripts
  +but I didn't have the access to the error_log file. I have asked the admin
  +to install this script and happily used it since then.
   
   <P>
  -The Perl modules are simply a thin xs layer on top of libapreq, making them
  -a lighter and faster alternative to CGI.pm and CGI::Cookie. See the
  -Apache::Request and Apache::Cookie documentation for more details and
  -eg/perl/ for examples.
  +If your scripts are running on these 'Get-free-site' servers, and your
  +cannot debug your script because you can't telnet to the server or can't
  +see the error_log, you can ask your sysadmin to install this script.
   
   <P>
  -Apache::Request and the libapreq are tied tight to the Apache API, which
  -there is no access to in a process running under mod_cgi.
  +Ok, here is the code:
   
   <P>
  -Get it from CPAN at $CPAN/authors/id/DOUGM/libapreq-x.xx.tar.gz or from <A
  -HREF="http://perl.apache.org/dist/libapreq-x.xx.tar.gz">http://perl.apache.org/dist/libapreq-x.xx.tar.gz</A>
  -. (replace x.xx with the current version)
  +<PRE>  #!/usr/bin/perl -Tw
  +  
  +  use strict;
  +  $|=1;
  +  
  +  my $default   = 10;
  +  my $error_log = &quot;/usr/local/apache/var/logs/error_log.1&quot;;
  +  use CGI;
  +  
  +  # untaint $ENV{PATH}
  +  $ENV{'PATH'} = '/bin:/usr/bin';
  +  delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
  +    
  +  my $q = new CGI;
  +  
  +  my $counts = (defined $q-&gt;param('count') and $q-&gt;param('count'))
  +    ? $q-&gt;param('count') : $default;
  +  
  +  print $q-&gt;header,
  +        $q-&gt;start_html(-bgcolor =&gt; &quot;white&quot;,
  +                     -title   =&gt; &quot;Error logs&quot;),
  +        $q-&gt;start_form,
  +        $q-&gt;center(
  +                 $q-&gt;b('How many lines to fetch? '),
  +                 $q-&gt;textfield('count',10,3,3),
  +                 $q-&gt;submit('', 'Fetch'),
  +                 $q-&gt;reset,
  +                ),
  +        $q-&gt;end_form,
  +        $q-&gt;hr;
  +  
  +  print($q-&gt;b(&quot;$error_log doesn't exist!!!&quot;)),exit unless -e $error_log;
  +  
  +  open LOG, &quot;tail -$counts $error_log|&quot; or die &quot;Can't open tail on $error_log :$!\n&quot;;
  +  my @logs = &lt;LOG&gt;;
  +  print $q-&gt;b('Note: Latest logs on the top'),$q-&gt;br;
  +  
  +  print &quot;&lt;UL&gt;\n&quot;;
  +  
  +    # format and colorize each line nicely
  +  foreach (reverse @logs) {
  +      s{
  +       \[(.*?)\]\s* # date
  +       \[(.*?)\]\s* # type of error 
  +       \[(.*?)\]\s* # client
  +       (.*)         # the message
  +      }
  +      {
  +        &quot;[$1] &lt;BR&gt; [&quot;.
  +        colorize($2,$2).
  +        &quot;] &lt;BR&gt; [$3] &lt;PRE&gt;&quot;.
  +        colorize($2,$4).
  +        &quot;&lt;/PRE&gt;&quot;
  +      }ex;
  +    print &quot;&lt;BR&gt;&lt;LI&gt;$_&lt;BR&gt;&quot;; 
  +  }
  +  
  +  print &quot;&lt;/UL&gt;\n&quot;;
  +  
  +  close LOG;
  +  
  +  #############
  +  sub colorize{
  +    my ($type,$context) = @_;
  +  
  +    my %colors = 
  +      (
  +       error  =&gt; 'red',
  +       crit   =&gt; 'black',
  +       notice =&gt; 'green',
  +       warn   =&gt; 'brown',
  +      );
  +  
  +    return exists $colors{$type}
  +        ? qq{&lt;B&gt;&lt;FONT COLOR=&quot;$colors{$type}&quot;&gt;$context&lt;/FONT&gt;&lt;/B&gt;}
  +        : $context;
  +  }
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Accessing_variables_from_the_cal">Accessing variables from the caller's package</A></H1></CENTER>
  +<P>
  +Sometimes you want to access some variables from the caller's package. One
  +way is to do:
   
   <P>
  +<PRE>  my $caller = caller;
  +  print qq[$caller --- ${&quot;${caller}::var&quot;}];
  +</PRE>
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Apache_PerlRun_Run_unaltered_">Apache::PerlRun - Run unaltered CGI scripts under mod_perl</A></H1></CENTER>
  +<CENTER><H1><A NAME="Handling_cookies">Handling cookies</A></H1></CENTER>
   <P>
  -See <A HREF="././porting.html#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>.
  +Unless you use some well known modules like CGI.pm you can handle the
  +cookies yourself.
  +
  +<P>
  +Cookies come in the $ENV{HTTP_COOKIE} variable. You can print the raw
  +cookie string as $ENV{HTTP_COOKIE}.
  +
  +<P>
  +This is a fairly well-known bit of code to take cookie values and put them
  +into a hash.
   
  +<P>
  +<PRE>  sub getCookies {
  +      # cookies are seperated by a semicolon and a space, this will
  +      # split them and return a hash of cookies
  +    local(@rawCookies) = split (/; /,$ENV{'HTTP_COOKIE'});
  +    local(%cookies);
  +  
  +    foreach(@rawCookies){
  +      ($key, $val) = split (/=/,$_);
  +      $cookies{$key} = $val;
  +    }
  +  
  +    return %cookies;
  +  }
  +</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>
  @@ -13327,7 +14066,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="browserbugs.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="perl.html">Next</A>      ]
  +	     [    <A HREF="perl.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="hardware.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -13340,7 +14079,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 05/17/1999
         </FONT>
       </B>
     </TD>
  @@ -13367,7 +14106,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Perl Reference</TITLE>
  +   <TITLE>mod_perl guide: Choosing an Operating System and Hardware</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -13389,279 +14128,433 @@
   <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>
  -Perl Reference</H1>
  +Choosing an Operating System and Hardware</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="modules.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="snippets.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="snippets.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="advocacy.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
  +
  +	<LI><A HREF="#Is_it_important_">Is it important?</A>
  +	<LI><A HREF="#Choosing_an_Operating_System">Choosing an Operating System</A>
  +	<UL>
  +
  +		<LI><A HREF="#Stability_and_Robustness">Stability and Robustness</A>
  +		<LI><A HREF="#Memory_Management">Memory Management</A>
  +		<LI><A HREF="#Memory_Leakages">Memory Leakages</A>
  +		<LI><A HREF="#Sharing_Memory">Sharing Memory</A>
  +		<LI><A HREF="#Cost_and_Support">Cost and Support</A>
  +		<LI><A HREF="#Discontinued_products">Discontinued products</A>
  +		<LI><A HREF="#OS_Releases">OS Releases</A>
  +	</UL>
  +
  +	<LI><A HREF="#Choosing_Hardware">Choosing Hardware</A>
  +	<UL>
  +
  +		<LI><A HREF="#Site_traffic">Site traffic</A>
  +		<LI><A HREF="#Cash">Cash</A>
  +		<LI><A HREF="#Memory">Memory</A>
  +		<LI><A HREF="#Internet_Connection">Internet Connection</A>
  +		<LI><A HREF="#Bottlenecks">Bottlenecks</A>
  +		<LI><A HREF="#Conclusion">Conclusion</A>
  +	</UL>
  +
  +</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="Is_it_important_">Is it important?</A></H1></CENTER>
  +<P>
  +You can invest a lot of time and money in server tuning and code rewriting
  +according the guidelines you have just learned, but your performance will
  +be really bad if you did not take into account the hardware demands, and
  +did not wisely chose the operating system suited for your needs. While the
  +tips below apply to any webserver, they are written for a mod_perl enabled
  +webservers' administrators.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Choosing_an_Operating_System">Choosing an Operating System</A></H1></CENTER>
  +<P>
  +First lets talk about Operating Systems (OS). While personally I am a Linux
  +devotee, I do not want to start yet another OS war. Assuming this, I will
  +try to define what you should be looking for, then when you know what do
  +you want from your OS, go find it. Visit the Web sites of operating systems
  +you are interested in. You can gauge user's opinions by searching relevant
  +discussions in newsgroup and mailing list archives such as Deja - <A
  +HREF="http://deja.com">http://deja.com</A> and eGroups - <A
  +HREF="http://egroups.com">http://egroups.com</A> . I will leave this fan
  +research up to you. But I would use linux :o) Just kidding...
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Stability_and_Robustness">Stability and Robustness</A></H2></CENTER>
  +<P>
  +Probably the most desired features in an OS are stability and robustness.
  +We are involved in an Internet business, which does not have normal working
  +hours, like many conventional businesses we know about (9pm to 5pm). We are
  +open 24 hours a day. We can not afford off line periods, for our customers
  +will go shop for another service like ours, unless you have a monopoly :) .
  +If the OS of your choice crashes every day or so, I would throw it away,
  +after doing a little investigation, for there are might be a reason for a
  +system crash. Like a runaway server that eats up all the memory and disk,
  +so we cannot blame the OS for that. Generally people who use the OS for
  +some time can tell you a lot about its stability.
   
  -	<LI><A HREF="#Coverage">Coverage</A>
  -	<LI><A HREF="#Using_global_variables_and_shari">Using global variables and sharing them between modules/packages</A>
  -	<UL>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Memory_Management">Memory Management</A></H2></CENTER>
  +<P>
  +You want an OS with a good memory management, some OSes are well known as
  +memory hogs. The same code can use twice as much memory on one OS compared
  +to the other. If the size of the mod_perl process is 10Mb and you have tens
  +of these running, it definitely adds up!
   
  -		<LI><A HREF="#Making_the_variables_global">Making the variables global</A>
  -		<LI><A HREF="#Making_the_variables_global_with">Making the variables global with strict pragma On</A>
  -		<LI><A HREF="#Using_Exporter_pm_to_share_globa">Using Exporter.pm to share global variables</A>
  -		<LI><A HREF="#Using_aliasing_perl_feature_to_s">Using aliasing perl feature to share global variables</A>
  -	</UL>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Memory_Leakages">Memory Leakages</A></H2></CENTER>
  +<P>
  +Some OSes and/or the libraries (like C libraries) suffer from memory
  +leakage. You cannot afford such a system, for you are already know that a
  +single mod_perl process sometimes serves thousands of requests before it
  +terminates. So if a leak occurs on every request, your memory demands will
  +be huge. Of course your code can be the cause of the memory leakages as
  +well (check out the <CODE>Apache::Leak</CODE>
  +module). Certainly you can lower the number of requests to be served over
  +the process' life, but performance degrades with this.
   
  -</UL>
  -<!-- INDEX END -->
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Sharing_Memory">Sharing Memory</A></H2></CENTER>
  +<P>
  +You want an OS with good memory sharing capabilities. As you have learned,
  +if you preload the modules and scripts at server startup, they are being
  +shared between the spawned children, at least for a part of a process' life
  +span, since memory pages are getting ``dirty'' and ceasing to be shared.
  +This feature can save you up a lot of memory!!!
   
  -<HR>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Cost_and_Support">Cost and Support</A></H2></CENTER>
  +<P>
  +If you are into a big business you are probably do not care to pay another
  +<CODE>$1000</CODE> for some fancy OS and to get the bundled support for it.
  +But if your resources are low, you will look for cheaper and free OSes.
  +Free does not mean bad, it can be quite opposite as we all either know from
  +our own experience or read about in news. Free OSes could have and do have
  +the best support you can find. It is very easy to understand - most of the
  +people are not rich and will try to use a cheaper or free OS first if it
  +does the work for them. Since it really fits their needs, many people keep
  +using it and eventually know it well enough to be able to provide support
  +for others in trouble. Why would they do this for free? For a real spirit
  +of the first days of the Internet, when there was no commercial Internet
  +and people helped each other, because someone helped them in first place. I
  +was there, I was touched by that spirit and I will do anything to keep this
  +spirit alive.
   
  -	     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>
  +But, let's get back to our world. We are living in material world, and our
  +bosses pay us to keep the systems running. So if you feel that you cannot
  +provide the support yourself and you do not trust the available free
  +resources, you must get an OS that has a company behind it to pay to blame
  +for any problems you encounter in hopes that your cries for help will be
  +heard and answered. Your boss wants to be able to sue someone if the
  +project has a problem caused by the external product that is being used in
  +the project. If you buy a product and the company selling it, claims
  +support, you have someone to sue. You do not have someone to sue other than
  +getting yourself fired if you go with Open Source and it fails.
   
  -	     <HR>
  +<P>
  +Also remember that if you spend less or zero money on OS and Software, you
  +will be able to buy a better and stronger hardware.
   
  -	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Coverage">Coverage</A></H1></CENTER>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Discontinued_products">Discontinued products</A></H2></CENTER>
   <P>
  -This new document was born because some users reluctant to learn perl prior
  -to jumping into a mod_perl. I will try to cover some of the most frequent
  -pure perl questions being asked at the list.
  +You have invested a lot into a developing of some proprietary software,
  +that is bundled with the OS you were developing on and for. Like you write
  +some mod_perl handler that takes an advantage of some proprietary features
  +of the OS and it will not run on any other OS. Things are under control,
  +the performance is great and you sing from happiness. But... one day the
  +company who wrote your beloved OS went bankrupt, which is not unlikely to
  +happen nowadays. You have got stuck with their last masterpiece and no
  +support! What you are going to do then? Invest more into porting the
  +software for another OS...
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Using_global_variables_and_shari">Using global variables and sharing them between modules/packages</A></H1></CENTER>
  +Everyone can be hit by this mini disaster, so it is better to watch the
  +background of the company when making your choice, but still you never know
  +what will happen in a next minute. The OSes in this hazard group are
  +completely developed by a single companies. Free OSes are probably less
  +susceptible to this, for development is distributed between many companies
  +and developers, so if a person who developed a really important part of the
  +kernel lost interest to continue, someone else will pick the falling flag
  +and continue from the same place. Of course if tomorrow some better project
  +shows up, developers might migrate there and finally drop the development,
  +but we are here not to let this happen.
  +
  +<P>
  +But you are the one to make the right decision...
  +
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Making_the_variables_global">Making the variables global</A></H2></CENTER>
  +<CENTER><H2><A NAME="OS_Releases">OS Releases</A></H2></CENTER>
   <P>
  -When you first wrote <CODE>$x</CODE> in your code you created a global
  -variable. It is visible everywhere in the file you have use it. or if
  -defined it inside a package - it is visible inside this package. But it
  -will work only if you do not use <CODE>strict</CODE> pragma and you <STRONG>HAVE</STRONG> to use this pragma if you want to run your scripts under mod_perl. Read <A HREF="././porting.html#strict_pragma">Strict pragma</A> to find out why.
  +Actively developed OSes generally try to keep the pace with the latest
  +technology developments, and continually optimize the kernel and other
  +parts of OS to become better and faster. Nowadays, Internet and Networking
  +in general are the hottest targets for system developers. Sometimes a
  +simple OS upgrade to a latest stable version, can save you an expensive
  +hardware upgrade. Also, remember that when you buy a new hardware, chances
  +are that the latest software will make the most out of it. Since while the
  +existing software (drivers) might support the new brand product because of
  +its back compatibility with previous products of the same family, it might
  +not take advantage of new features. It means that you could spend much less
  +money for almost the same functionality if you were to buy a previous model
  +of the same product.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Making_the_variables_global_with">Making the variables global with strict pragma On</A></H2></CENTER>
  +<CENTER><H1><A NAME="Choosing_Hardware">Choosing Hardware</A></H1></CENTER>
  +<P>
  +While I am not fond of the idea of updating this section every day a new
  +processor or memory type comes out, exactly like with OS choosing
  +guidelines, I will only hint what should you look after and persuade you
  +that sometimes the most expensive machine is not the one which provides the
  +best performance.
  +
   <P>
  -First you use :
  +Your demands are bound to many aspects and components. Let's discuss some
  +of them.
   
   <P>
  -<PRE>  use strict;
  -</PRE>
  +In discussion course you might meet some unfamiliar terms, here are some of
  +them:
  +
  +<UL>
  +<P><LI>
   <P>
  -Then you use:
  +Clustering - a bunch of machines connected together to perform one big or
  +many small computational tasks in a reasonable time.
   
  +<P><LI>
   <P>
  -<PRE> use vars qw($scalar %hash @array);
  -</PRE>
  +Balance loading - users can remember only a name of one of your machines -
  +namely of your server, but it cannot stand the heavy load, so you use a
  +clustering approach, distributing the load over a number of machines. The
  +central server, the one users access when they type the name of the
  +service, works as a dispatcher, by redirecting requests to the rest of the
  +machines, sometimes it also collects the results and return them to the
  +users. One of the advantages is that you can take one of the machines down
  +for a repair or upgrade, and your service will still work - the main server
  +will not dispatch the requests to the machine that was taken down. I will
  +just say that there are many load balancing techniques.
  +
  +<P><LI>
   <P>
  -Starting from this moment the variables are global in the package you
  -defined them, if you want to share global variables between packages, here
  -what you can do.
  +NIC - Network Interface Card.
  +
  +<P><LI>
  +<P>
  +RAM - Random Access Memory
  +
  +<P><LI>
  +<P>
  +RAID - META
   
  +</UL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Using_Exporter_pm_to_share_globa">Using Exporter.pm to share global variables</A></H2></CENTER>
  +<CENTER><H2><A NAME="Site_traffic">Site traffic</A></H2></CENTER>
   <P>
  -Assume that you want to share the <CODE>CGI.pm</CODE>'s object (I will use <CODE>$q</CODE>) between your modules. For example you create it in the <CODE>script.pl</CODE>, but want it to be visible in <CODE>My::HTML</CODE>. First - you make <CODE>$q</CODE> global.
  +If you are building a fans' site, but want to amaze your friends with
  +mod_perl guest book, an old 486 machine will do it. If you are into a
  +serious business, it is very important to build a scalable server, so if
  +your service is successful and becomes popular, you get your server's
  +traffic doubled every few days, you should be ready to add more resources
  +dynamically. While we can define the webserver scalability more precisely,
  +the important thing is to make sure that you can add more power to your
  +<CODE>webserver(s)</CODE> without investing additional money into a
  +software developing (almost, you will need a software to connect your
  +servers if you add more of them). It means that you should choose a
  +hardware/OS that can talk to other machines and become a part of the
  +cluster.
   
   <P>
  -<PRE>  script.pl:
  -  ----------------
  -  use vars qw($q);
  -  use CGI;
  -  use My::HTML qw($q);
  -  $q = new CGI;
  -  
  -  My::HTML::printmyheader();
  -  ----------------
  -</PRE>
  +From the other hand if you prepare for a big traffic and buy a monster to
  +do the work for you, what happens if your service does not prove to be as
  +successful as you thought it would be. Then you spent too much money and
  +meanwhile there were a new faster processors and other hardware components
  +released, so you loose again.
  +
   <P>
  -Note that we have imported <CODE>$q</CODE> from <CODE>My::HTML</CODE>. And the <CODE>My::HTML</CODE>
  -which does the export of <CODE>$q</CODE>:
  +Wisdom and prophecy , that's all it takes :)
   
   <P>
  -<PRE>  My/HTML.pm
  -  ----------------
  -  package My::HTML;
  -  use strict;
  -  
  -  BEGIN {
  -    use Exporter ();
  -  
  -    @My::HTML::ISA         = qw(Exporter);
  -    @My::HTML::EXPORT      = qw();
  -    @My::HTML::EXPORT_OK   = qw($q);
  -  
  -  }
  -  
  -  use vars qw($q);
  -  
  -  sub printmyheader{
  -    # Whatever you want to do with $q... e.g.
  -    print $q-&gt;header();
  -  }
  -  -------------------
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Cash">Cash</A></H2></CENTER>
   <P>
  -So the <CODE>$q</CODE> is being shared between the <CODE>My::HTML</CODE> package and the
  -<CODE>script.pl</CODE>. It will work vice versa as well, if you create the object in the <CODE>My::HTML</CODE> but use it in the <CODE>script.pl</CODE>. You have a true sharing, since if you change <CODE>$q</CODE> in <CODE>script.pl</CODE>, it will be changed in <CODE>My::HTML</CODE> as well.
  +Everybody knows that Internet is a cash hole, what you throw in, hardly
  +comes back. This is not always correct, but there is a lot of wisdom in
  +these words. While you have to invest money to build a decent service, it
  +can be cheaper! You can spend as much as 10 times more money on a strong
  +new machine, but get only a 10% improve in performance. Remember that
  +processor that was born 4 years ago is still very mighty.
   
   <P>
  -What if you need to share <CODE>$q</CODE> between more than 2 packages? For example you want My::Doc to share <CODE>$q</CODE> as well.
  +If you really need a lot of power do not think about a single strong
  +machine (unless you have money to throw away), think about clustering and
  +load balancing. You can probably buy 10 times more older but very cheap
  +machines and have a 8 times more power, then purchasing only one single new
  +machine. Why is that? Because as I mentioned before generally the
  +performance improvement is marginal while the price is much bigger. Because
  +10 machines will do a faster Hard Disk IO (Input/Output), then one single
  +machine even if the disk is much faster. Yes, you have more administration
  +overhead, but there is a chance you will have it anyway, for in a short
  +time the machine you have just invested into will not stand the load and
  +you will have to purchase more and think how to implement the load
  +balancing and file system distribution.
   
   <P>
  -You leave the <CODE>My::HTML</CODE> untouched, modify the script.pl to include:
  +Why I am so convinced? Facts! Look at the most used services on the
  +Internet: search engines, email servers and alike - most of them are using
  +clustering approach. While you will not always notice that, they do it by
  +hiding the real implementation behind the proxy servers.
   
   <P>
  -<PRE> use My::Doc qw($q);
  +<PRE> =head2 IO performance
   </PRE>
   <P>
  -And write the <CODE>My::Doc</CODE> exactly like <CODE>My::HTML</CODE> - of course that the content is different :).
  +If your service is IO bound (does a lot of read/write operations to your
  +disk, remember that relational DataBases are sitting on disk as well) you
  +need a very fast disk. So you should not spend money on a Video card and
  +monitor (monochrome card and 14`` B&amp;W will do for server
  +configuration), but rather look for the best price/performance in disks (of
  +course asking around for a solid firm, whose HDs are not getting corrupted
  +at all.) With money in hand you should think about getting a RAID system.
  +RAID is generally a box with many HDs. It is capable of reading/writing
  +data much faster, and is protected against disk corruptions. It does this
  +by duplicating the same data over a number of disks, so if one gets
  +corrupted the RAID detects it and the data is still correct on the
  +duplicated disks. You must think about RAID or similar systems if you have
  +an enormous data set to serve. (What is an enormous data set nowadays?).
   
   <P>
  -One possible pitfall is when you want to use the <CODE>My::Doc</CODE> in both
  -<CODE>My::HTML</CODE> and <CODE>script.pl</CODE>. Only if you add:
  +Ok, we have a fast disk, what's next? You need a fast disk controller. So
  +either you should use the one embedded on your motherboard or you should
  +plug a controller card if the one you have onboard is not good enough.
   
   <P>
  -<PRE>  use My::Doc qw($q);
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Memory">Memory</A></H2></CENTER>
   <P>
  -Into a <CODE>My::HTML</CODE>, the <CODE>$q</CODE> will be shared. Otherwise <CODE>My::Doc</CODE> will not share the <CODE>$q</CODE> anymore. To make things clear here is the code:
  +How much RAM (Randomly Accessed Memory) do you need? Nowadays, chances are
  +you will hear: ``Memory is cheap, the more you buy the better''. But how
  +much is enough? The answer pretty straightforward: ``You do not want your
  +machine to swap''. When the CPU needs to write something into memory, but
  +notices that it is already full, it takes the least frequently used memory
  +pages (4k/page on average OS) and swaps them out. Swapping out means
  +copying to the disk into a special partition or file called swap and
  +deleting from the real memory. When another process asks the CPU to access
  +another page, but CPU cannot find the memory page in RAM (it was just
  +swapped out), it goes and brings it from the swap (swapping in). If memory
  +is small, swapping (in/out) happens too frequently, the CPU becomes too
  +busy swapping pages in and out, the HD is working hard to read/write the
  +swapped out pages, and the whole performance of the system is going down.
  +Sometimes your swap partition can become full as well and your system might
  +die.
   
  -<P>
  -<PRE>  script.pl:
  -  ----------------
  -  use vars qw($q);
  -  use CGI;
  -  use My::HTML qw($q);
  -  use My::Doc  qw($q);
  -  $q = new CGI;
  -  
  -  My::HTML::printmyheader();
  -  ----------------
  -</PRE>
  -<P>
  -<PRE>  My/HTML.pm
  -  ----------------
  -  package My::HTML;
  -  use strict;
  -  
  -  BEGIN {
  -    use Exporter ();
  -  
  -    @My::HTML::ISA         = qw(Exporter);
  -    @My::HTML::EXPORT      = qw();
  -    @My::HTML::EXPORT_OK   = qw($q);
  -  
  -  }
  -  
  -  use vars     qw($q);
  -  use My::Doc  qw($q);
  -  
  -  sub printmyheader{
  -    # Whatever you want to do with $q... e.g.
  -    print $q-&gt;header();
  -  
  -    My::Doc::printtitle('Guide');
  -  }
  -  -------------------
  -</PRE>
   <P>
  -<PRE>  My/Doc.pm
  -  ----------------
  -  package My::Doc;
  -  use strict;
  -  
  -  BEGIN {
  -    use Exporter ();
  -  
  -    @My::Doc::ISA         = qw(Exporter);
  -    @My::Doc::EXPORT      = qw();
  -    @My::Doc::EXPORT_OK   = qw($q);
  -  
  -  }
  -  
  -  use vars qw($q);
  -  
  -  sub printtitle{
  -    my $title = shift || 'None';
  -    
  -    print $q-&gt;h1($title);
  -  }
  -  -------------------
  -</PRE>
  +How do you make a decision? You know what is the highest page request rate
  +your service has and how much time an average request takes. Now you can
  +calculate how many servers do you need. Knowing the maximum size any of
  +your servers can get, you know how much memory do you need. You probably
  +need less memory that you have calculated if your OS supports memory
  +sharing and you know how to deploy this feature (preloading the modules and
  +scripts at server's startup). Do not forget that other essential system
  +processes need memory as well, so you should not plan for the webserver
  +only, but to take into an account all processes to be run on your system.
  +Remember that requests can be queued, so you can afford your client to wait
  +a few moments, while some server comes to service it, your numbers will be
  +more correct, since you generally do not have the highest load, but you
  +should be ready to bear the picks. So you need to reserve at least 20% of
  +free memory for peak situations. Many sites were reported to crash a few
  +moments after some scooping news about them were posted, and unexpected
  +number of requests suddenly came in. If you are about to announce something
  +cool, be aware of possible consequences.
  +
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Using_aliasing_perl_feature_to_s">Using aliasing perl feature to share global variables</A></H2></CENTER>
  +<CENTER><H2><A NAME="Internet_Connection">Internet Connection</A></H2></CENTER>
  +<P>
  +You have the best hardware you could get, but the service is still
  +crawling. Make sure you have a fast Internet connection. Not _fast_ as your
  +ISP claims it to be, but fast as it should be. The ISP might have a very
  +good connection to the Internet, but put many clients on the same line. If
  +these are heavy clients your traffic will have to share the same line, thus
  +your speed is effectively limited. Think about a dedicated connection and
  +make sure it is truly dedicated, trust the ISP but check it!
  +
   <P>
  -As the title says you can import a variable into a script/module without
  -using an Exporter.pm. I have found it useful to keep all the configuration
  -variables in one module <CODE>My::Config</CODE>. But then I have to export all the variables in order to use them in other
  -modules, which is bad for two reasons: polluting other packages' name
  -spaces with extra tags which rise up the memory requirements, adding an
  -overhead of keeping track of what variables should be exported from the
  -configuration module and what imported for some particular package. I solve
  -this problem by keeping all the variables in one hash <CODE>%c</CODE> and exporting only it. Here is an example of <CODE>My::Config</CODE>:
  +The idea of having a connection to <STRONG>The Internet</STRONG> is a little misleading. Many Web hosting and co-location companies have
  +large amounts of bandwidth, but still have poor connectivity. The public
  +exchanges, such as MAE-East and MAE-West, frequently become overloaded, yet
  +many ISPs depend on these exchanges.
   
   <P>
  -<PRE>  package My::Config;
  -  use strict;
  -  use vars qw(%c);
  -  %c = (
  -    # All the configs go here
  -    scalar_var =&gt; 5,
  -  
  -    array_var  =&gt; [
  -                   foo,
  -                   bar,
  -                  ],
  -  
  -    hash_var   =&gt; {
  -                   foo =&gt; 'Foo',
  -                   bar =&gt; 'BARRR',
  -                  },
  -  );
  -</PRE>
  +Private peering means that providers can exchange traffic much quicker.
  +
   <P>
  -Now in packages that want to use the configuration variables I have either
  -to use the fully qualified names like <CODE>$My::Config::test</CODE>, which I dislike or import them as described in the previous section. But
  -hey, since we have only one variable to handle, we can make things even
  -simpler and save the loading of the <CODE>Exporter.pm</CODE> package. We will use aliasing perl feature for exporting and saving the
  -keystrokes:
  +Also, if your Web site is of global interest, check that the ISP has good
  +global connectivity. If the Web site is going to be visited mostly by
  +people in a certain country or region, your server should probably be
  +located there.
   
   <P>
  -<PRE>  package My::HTML;
  -  use strict;
  -    # Global Configuration now aliased to global %c
  -  use My::Config ();
  -  use vars qw(%c);
  -  *c = \%My::Config::c;
  -  
  -    # Now you can access the variables from the My::Config
  -  print $c{scalar_val};
  -  print $c{array_val}[0];
  -  print $c{hash_val}{foo};
  -</PRE>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Bottlenecks">Bottlenecks</A></H2></CENTER>
   <P>
  -Of course <CODE>$c</CODE> is global everywhere you use it as described
  -above, and if you change it somewhere it will affect any other packages you
  -have aliased <CODE>$My::Config::c</CODE> to.
  +The most important thing to understand is that you might use the most
  +expensive components, but still get a bad performance. Why? Let me
  +introduce you to this annoying word: A bottleneck.
   
   <P>
  -Note that aliases work either with global or <CODE>local()</CODE> vars - you cannot write:
  +A machine is an aggregate of many small and big components. Each one of
  +them can become a bottleneck. If you have a fast processor but a small
  +amount of RAM (memory), the processor will be under utilized waiting for
  +the kernel to swap memory pages in and out, because memory is too small to
  +fit at least the most used ones. If you have a lot of memory and a fast
  +processor and a fast disk, but a slow controller - the performance will be
  +bad, and you have wasted the money.
   
  -<P>
  -<PRE>  my *c = \%My::Config::c;
  -</PRE>
   <P>
  -Which is an error. But you can:
  +Of course use a NIC (Network Interface Card) that does not create a
  +bottleneck. If it is slow, the whole service is slow.
   
   <P>
  -<PRE>  local *c = \%My::Config::c;
  -</PRE>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Conclusion">Conclusion</A></H2></CENTER>
  +<P>
  +To optimally use your money, you have to either understand the hardware
  +very well, so you will know what to pick, or you should hire a
  +knowledgeable hardware consultants and employ them on a constant basis,
  +since your demands will probably change as time goes on, and your HW should
  +be adapted with each change you make.
  +
  +<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
  @@ -13671,7 +14564,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="modules.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="snippets.html">Next</A>      ]
  +	     [    <A HREF="snippets.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="advocacy.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -13684,7 +14577,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/04/1999
         </FONT>
       </B>
     </TD>
  @@ -13711,7 +14604,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Code Snippets</TITLE>
  +   <TITLE>mod_perl guide: mod_perl Advocacy</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -13733,18 +14626,14 @@
   <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>
  -Code Snippets</H1>
  +mod_perl Advocacy</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="perl.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="help.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="hardware.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="help.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#Sending_MIME_headers">Sending MIME headers</A>
  -	<LI><A HREF="#How_to_avoid_printing_the_header">How to avoid printing the header more than once.</A>
  -	<LI><A HREF="#More_on_relative_paths">More on relative paths</A>
  -	<LI><A HREF="#Watching_the_error_log_file_with">Watching the error_log file without telneting to the server.</A>
  -	<LI><A HREF="#Accessing_variables_from_the_cal">Accessing variables from the caller's package</A>
  -	<LI><A HREF="#Handling_cookies">Handling cookies</A>
  +	<LI><A HREF="#Thoughts_about_scalability">Thoughts about scalability</A>
  +	<LI><A HREF="#The_boss_and_the_developer">The boss and the developer</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -13761,204 +14650,67 @@
   	     <HR>
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<P>
  -<CENTER><H1><A NAME="Sending_MIME_headers">Sending MIME headers</A></H1></CENTER>
  -<P>
  -By default, mod_perl does not send any headers by itself, however, you may
  -wish to change this behavior by setting in config file: 
  -
  -<P>
  -<PRE>  PerlSendHeader On
  -</PRE>
  -<P>
  -The safest bet is to use CGI.pm's <CODE>print header();</CODE> method (If you use this, you don't need the above setting)
  -
  -<P>
  -Also there is $ENV{PERL_SEND_HEADER} to see if PerlSendHeader is On or Off.
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="How_to_avoid_printing_the_header">How to avoid printing the header more than once.</A></H1></CENTER>
  -<P>
  -I'm sure you have been in the situations, where you wish you knew whether
  -the MIME header has been already printed. Since if it was printing it again
  -will cause an ugly ``Content-type: ...'' string show up at the web page. So
  -how do we solve it? With help of closure.
  -
  -<P>
  -Just copy the code below as it is, including the block's curly parentheses.
  -And everywhere in your code use the <CODE>print_header()</CODE> sub to
  -print the header. <CODE>$need_header</CODE> is the same beast as static variable in C, so it remembers its value from
  -call to call.
  -
  -<P>
  -<PRE>  {
  -    my $need_header = 1;
  -    sub print_header {
  -      print header(@_),$need_header = 0 if $need_header;
  -    }
  -  }
  -</PRE>
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="More_on_relative_paths">More on relative paths</A></H1></CENTER>
  -<P>
  -Many use a relative require call, or write to the file in the current or
  -relative to the current directory. But this will fail if you wouldn't
  -<CODE>chdir()</CODE> into the directory first. So you have to either do
  -this in the code or to use a nice <CODE>FindBin.pm</CODE> package.
  -
  -<P>
  -<PRE>  use FindBin qw($Bin);
  -  use lib $Bin;
  -  # or
  -  open IN, &quot;$Bin/foo.txt&quot;;
  -</PRE>
  -<P>
  -Now <CODE>$Bin</CODE> includes the path of the directory the script resides on, so you can move
  -the script from one directory to the other and call it from anywhere else,
  -the paths will be always correct.
  -
   <P>
  -It's different from using the ``./foo'', for you have to chdir to the
  -directory the script located at first. (Think about crontabs!!!)
  -
  -<P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Watching_the_error_log_file_with">Watching the error_log file without telneting to the server.</A></H1></CENTER>
  -<P>
  -I wrote this script long time ago, when I have had to debug my cgi scripts
  -but I didn't have the access to the error_log file. I have asked the admin
  -to install this script and happily used it since then.
  -
  -<P>
  -If your scripts are running on these 'Get-free-site' servers, and your
  -cannot debug your script because you can't telnet to the server or can't
  -see the error_log, you can ask your sysadmin to install this script.
  -
  +<CENTER><H1><A NAME="Thoughts_about_scalability">Thoughts about scalability</A></H1></CENTER>
   <P>
  -Ok, here is the code:
  +It depends on what you ought to do on the web. If all you want is a simple
  +guest book or very simple DB gateway you can get away with any of
  +EASY_AND_FAST_TO_DEVELOP_TOOLS (Exchange, MS IIS, Lotus Notes, etc). The
  +problem is that as my experience shows, in short terms you will want more
  +functionality, so you start looking for really creative ways to get this
  +functionalily from these _easy_ tools, and when you make it if at all, your
  +boss asks for even more functionality and then you understand that you have
  +got no scalability and you have to port all your code to mod_perl or
  +another powerful equivalent. Then you look back and see how much time and
  +money was wasted with that EASY_AND_FAST_TO_DEVELOP_TOOLS.
   
  -<P>
  -<PRE>  #!/usr/bin/perl -Tw
  -  
  -  use strict;
  -  $|=1;
  -  
  -  my $default   = 10;
  -  my $error_log = &quot;/usr/local/apache/var/logs/error_log.1&quot;;
  -  use CGI;
  -  
  -  # untaint $ENV{PATH}
  -  $ENV{'PATH'} = '/bin:/usr/bin';
  -  delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
  -    
  -  my $q = new CGI;
  -  
  -  my $counts = (defined $q-&gt;param('count') and $q-&gt;param('count'))
  -    ? $q-&gt;param('count') : $default;
  -  
  -  print $q-&gt;header,
  -        $q-&gt;start_html(-bgcolor =&gt; &quot;white&quot;,
  -                     -title   =&gt; &quot;Error logs&quot;),
  -        $q-&gt;start_form,
  -        $q-&gt;center(
  -                 $q-&gt;b('How many lines to fetch? '),
  -                 $q-&gt;textfield('count',10,3,3),
  -                 $q-&gt;submit('', 'Fetch'),
  -                 $q-&gt;reset,
  -                ),
  -        $q-&gt;end_form,
  -        $q-&gt;hr;
  -  
  -  print($q-&gt;b(&quot;$error_log doesn't exist!!!&quot;)),exit unless -e $error_log;
  -  
  -  open LOG, &quot;tail -$counts $error_log|&quot; or die &quot;Can't open tail on $error_log :$!\n&quot;;
  -  my @logs = &lt;LOG&gt;;
  -  print $q-&gt;b('Note: Latest logs on the top'),$q-&gt;br;
  -  
  -  print &quot;&lt;UL&gt;\n&quot;;
  -  
  -    # format and colorize each line nicely
  -  foreach (reverse @logs) {
  -      s{
  -       \[(.*?)\]\s* # date
  -       \[(.*?)\]\s* # type of error 
  -       \[(.*?)\]\s* # client
  -       (.*)         # the message
  -      }
  -      {
  -        &quot;[$1] &lt;BR&gt; [&quot;.
  -        colorize($2,$2).
  -        &quot;] &lt;BR&gt; [$3] &lt;PRE&gt;&quot;.
  -        colorize($2,$4).
  -        &quot;&lt;/PRE&gt;&quot;
  -      }ex;
  -    print &quot;&lt;BR&gt;&lt;LI&gt;$_&lt;BR&gt;&quot;; 
  -  }
  -  
  -  print &quot;&lt;/UL&gt;\n&quot;;
  -  
  -  close LOG;
  -  
  -  #############
  -  sub colorize{
  -    my ($type,$context) = @_;
  -  
  -    my %colors = 
  -      (
  -       error  =&gt; 'red',
  -       crit   =&gt; 'black',
  -       notice =&gt; 'green',
  -       warn   =&gt; 'brown',
  -      );
  -  
  -    return exists $colors{$type}
  -        ? qq{&lt;B&gt;&lt;FONT COLOR=&quot;$colors{$type}&quot;&gt;$context&lt;/FONT&gt;&lt;/B&gt;}
  -        : $context;
  -  }
  -</PRE>
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Accessing_variables_from_the_cal">Accessing variables from the caller's package</A></H1></CENTER>
  -<P>
  -Sometimes you want to access some variables from the caller's package. One
  -way is to do:
  +The point is that if you are serious about Internet and script driven
  +sites, sooner or later you will need a lot of flexibility and functionality
  +from your script/code base. So you better choose a development platform
  +with power of doing things your way at first place. While you might spend a
  +little more time and money to learn the language and its concepts, and to
  +code the basic skeleton, later code extension and modifications would be a
  +snap.
   
   <P>
  -<PRE>  my $caller = caller;
  -  print qq[$caller --- ${&quot;${caller}::var&quot;}];
  -</PRE>
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Handling_cookies">Handling cookies</A></H1></CENTER>
  +<CENTER><H1><A NAME="The_boss_and_the_developer">The boss and the developer</A></H1></CENTER>
   <P>
  -Unless you use some well known modules like CGI.pm you can handle the
  -cookies yourself.
  +While there is a known factor of boss character in the life of developer,
  +the developer should make an investigation work before he goes to ask for
  +an approval to go with mod_perl. Personally, when I discovered mod_perl I
  +did a lot of testing and coding at home and at work. Once I have had a
  +working heavy application, I came to my boss with 2 URLs - one for the
  +plain CGI server and the other for mod_perl enabled server. It took about
  +30 secs for my boss to say: ``Go with it''. Of course the moment I did it,
  +I have had to provide all the support for other developers, that is why I
  +took my time to learn it in first place (that is how this guide was born!).
   
   <P>
  -Cookies come in the $ENV{HTTP_COOKIE} variable. You can print the raw
  -cookie string as $ENV{HTTP_COOKIE}.
  +Most chances that you are doomed to failure if you are showing some very
  +fast working site, and persuade your boss to give it a try but the moment
  +you start to code/port the scripts your are getting stuck cause you are
  +unfamiliar with mod_perl pecularities. If your boss follows your
  +development process closely and sees you not making any progress, he might
  +say - forget it, we fall back to old foo platform. And if this happens, you
  +made the mistake twice - you are not developing under mod_perl and chances
  +that your boss will give you and mod_perl a second chances are very little.
   
   <P>
  -This is a fairly well-known bit of code to take cookie values and put them
  -into a hash.
  +I am not here to discourage you to advocate mod_perl at your working place.
  +I am here to warn you that if you want to advocate something, you cannot
  +start doing this based on the naked facts. You have to learn the technology
  +in subject in first place, get acquanted with the ways you can get helped
  +in case of trouble. The ideal scenario would be to show your boss a heavy
  +CGI which is running much faster under mod_perl, and when she gets
  +impressed, ask for an evaluation time (I know that the chances you get it
  +are not very high, that is why I called it ideal), argument the need for
  +evaluation and studying time with an enormous time save-up in the future.
  +When this time is out make sure you can provide the support for mod_perl or
  +at least to be a connecting bridge between your organization and the
  +mod_perl community.
   
  -<P>
  -<PRE>  sub getCookies {
  -      # cookies are seperated by a semicolon and a space, this will
  -      # split them and return a hash of cookies
  -    local(@rawCookies) = split (/; /,$ENV{'HTTP_COOKIE'});
  -    local(%cookies);
  -  
  -    foreach(@rawCookies){
  -      ($key, $val) = split (/=/,$_);
  -      $cookies{$key} = $val;
  -    }
  -  
  -    return %cookies;
  -  }
  -</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>
  @@ -13969,7 +14721,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="perl.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="help.html">Next</A>      ]
  +	     [    <A HREF="hardware.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="help.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -13982,7 +14734,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/05/1999
         </FONT>
       </B>
     </TD>
  @@ -14033,7 +14785,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>
   Getting Helped and Further Learning</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="snippets.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="download.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="advocacy.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="download.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  @@ -14339,7 +15091,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="snippets.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="download.html">Next</A>      ]
  +	     [    <A HREF="advocacy.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="download.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  
  
  
  1.14      +124 -3    modperl-site/guide/config.html
  
  Index: config.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/config.html,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- config.html	1999/05/17 20:47:31	1.13
  +++ config.html	1999/06/05 17:47:11	1.14
  @@ -43,6 +43,8 @@
   			<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>
  @@ -59,12 +61,13 @@
   		<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 basis. </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 -->
   
  @@ -352,6 +355,97 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="The_confusion_with_use_clause_">The confusion with use() clause at the server startup?</A></H3></CENTER>
  +<P>
  +Many people wonder, why there is a need for duplication of <CODE>use()</CODE>
  +clause both in startup file and in the script itself. The question rises
  +from misunderstanding of the <CODE>use()</CODE> operand. <CODE>use()</CODE> consists of two other operands, namely <CODE>require()</CODE> and <CODE>import()</CODE>. So when you write:
  +
  +<P>
  +<PRE>  use Foo qw(bar);
  +</PRE>
  +<P>
  +perl actually does:
  +
  +<P>
  +<PRE>  require Foo.pm;
  +  import qw(bar);
  +</PRE>
  +<P>
  +When you write:
  +
  +<P>
  +<PRE>  use Foo qw();
  +</PRE>
  +<P>
  +perl actually does:
  +
  +<P>
  +<PRE>  require Foo.pm;
  +  import qw();
  +</PRE>
  +<P>
  +which means that the caller does not want any symbols to be imported. Why
  +is this important? Since some modules has <CODE>@EXPORT</CODE> set to some tags to be exported by default and when 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.
  +
  +<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:
  +
  +<P>
  +<PRE>  package MyModule;
  +  
  +  sub {
  +    my $r = shift;
  +  
  +    ## Cool stuff goes here
  +  
  +    return OK;
  +  }
  +</PRE>
  +<P>
  +<PRE>  1;
  +</PRE>
  +<P>
  +You would either need to add:
  +
  +<P>
  +<PRE>  use Apache::Constants qw( OK );
  +</PRE>
  +<P>
  +Or instead of <CODE>return OK;</CODE> say:
  +
  +<P>
  +<PRE>  return Apache::Constants::OK;
  +</PRE>
  +<P>
  +See the manpage/perldoc on <CODE>Exporter</CODE> and <CODE>perlmod</CODE> for more on import.
  +
  +<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.
  +
  +<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.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Running_apachectl_configtest_o">Running 'apachectl configtest' or 'httpd -t'</A></H1></CENTER>
   <P>
   <CODE>apachectl configtest</CODE> tests the configuration file without starting the server. You can safely
  @@ -690,12 +784,17 @@
   
   <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 basis.</A></H2></CENTER>
  +<CENTER><H2><A NAME="Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host or per-location basis.</A></H2></CENTER>
   <P>
   You can use 'PerlSetEnv PERL5LIB ...' or a PerlFixupHandler w/ the lib
   pragma.
   
   <P>
  +Even a better way is to use <A HREF="././modules.html#Apache_PerlVINC_set_a_differe">Apache::PerlVINC</A>
  +
  +
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="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>
  @@ -759,6 +858,28 @@
   Another approach is to modify httpd sources to reveal no unwanted
   information, so if you know the port the <CODE>HEAD</CODE> request will return an empty or phony <CODE>Server:</CODE> field.
   
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A></H1></CENTER>
  +<P>
  +Let's say that you want all the file in a specific directory and below to
  +be handled the same way, but a few of them to be handled somewhat
  +different. For example:
  +
  +<P>
  +<PRE>  &lt;Directory /home/foo&gt;
  +    &lt;FilesMatch &quot;\.(html|txt)$&quot;&gt;
  +      SetHandler perl-script
  +      PerlHandler Apache::AddrMunge
  +    &lt;/FilesMatch&gt;
  +  &lt;/Directory&gt;
  +</PRE>
  +<P>
  +Alternatively you can use &lt;Files&gt; inside an <CODE>.htaccess</CODE> file.
  +
  +<P>
  +Note that you cannot have <CODE>Files</CODE> derective inside <CODE>Location</CODE>, but you can have <CODE>Files</CODE> inside <CODE>Directory</CODE>.
  +
   <P><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>
  @@ -782,7 +903,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/15/1999
  +	     <BR>Last Modified at 06/05/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.14      +4 -4      modperl-site/guide/control.html
  
  Index: control.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/control.html,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- control.html	1999/05/08 17:46:29	1.13
  +++ control.html	1999/06/05 17:47:12	1.14
  @@ -25,7 +25,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="multiuser.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="status.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  @@ -487,7 +487,7 @@
   <CENTER><H1><A NAME="Running_server_in_a_single_mode">Running server in a single mode</A></H1></CENTER>
   <P>
   Often while developing new code, you will want to run the server in single
  -process mode. See <A HREF="././porting.html#Sometimes_it_Works_Sometimes_Not">Sometimes it works Sometimes Not</A> and <A HREF="././porting.html#Name_collisions_with_Modules_and">Names collisions with Modules and libs</A>
  +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.
   
  @@ -959,7 +959,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="multiuser.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="status.html">Next</A>      ]
  +	     [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="security.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -972,7 +972,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/04/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.3       +68 -14    modperl-site/guide/databases.html
  
  Index: databases.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/databases.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- databases.html	1999/05/17 20:47:31	1.2
  +++ databases.html	1999/06/05 17:47:12	1.3
  @@ -41,18 +41,20 @@
   		<UL>
   
   			<LI><A HREF="#The_morning_bug">The morning bug</A>
  +			<LI><A HREF="#Opening_a_connection_with_differ">Opening a connection with different parameters</A>
   			<LI><A HREF="#Cannot_find_the_DBI_handler">Cannot find the DBI handler</A>
   			<LI><A HREF="#Apache_DBI_does_not_work">Apache:DBI does not work</A>
   		</UL>
   
  -		<LI><A HREF="#Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A>
  -		<UL>
  -
  -			<LI><A HREF="#Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A>
  -			<LI><A HREF="#My_DB_module">My::DB module</A>
  -			<LI><A HREF="#My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A>
  -		</UL>
  +	</UL>
   
  +	<LI><A HREF="#mysql_use_result_vs_mysql_store">mysql_use_result vs. mysql_store_result.</A>
  +	<LI><A HREF="#Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A>
  +	<UL>
  +
  +		<LI><A HREF="#Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A>
  +		<LI><A HREF="#My_DB_module">My::DB module</A>
  +		<LI><A HREF="#My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A>
   	</UL>
   
   </UL>
  @@ -234,6 +236,25 @@
   Where 172800 secs equal to 48 hours. And it works.
   
   <P>
  +Note that starting from ver. <CODE>0.82</CODE>, <CODE>Apache::DBI</CODE> implements ping inside the <CODE>eval</CODE> block, so if the handle has been timouted, it should reconnect without
  +creating the morning bug.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Opening_a_connection_with_differ">Opening a connection with different parameters</A></H3></CENTER>
  +<P>
  +Q: Currently I am running into a problem where I found out that
  +<CODE>Apache::DBI</CODE> insists that the connection will opened exactly the same way before it will
  +decide to use a cached connection. I.e. if I have one script that sets <CODE>LongReadLen</CODE> and one that does not, it will be two different connections. Instead of
  +having a max of 40 open connections, I end up with 80.
  +
  +<P>
  +A: indeed, <CODE>Apache::DBI</CODE> returns a cached database handle, if and only if all parameters including
  +all options are identical. But you are free to modify the handle right
  +after you got it from the cache. Initiate the connections always using the
  +same parameters and set <CODE>LongReadLen</CODE> afterwards.
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H3><A NAME="Cannot_find_the_DBI_handler">Cannot find the DBI handler</A></H3></CENTER>
   <P>
  @@ -265,8 +286,43 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A></H2></CENTER>
  +<CENTER><H1><A NAME="mysql_use_result_vs_mysql_store">mysql_use_result vs. mysql_store_result.</A></H1></CENTER>
   <P>
  +Since many mod_perl developers uses mysql as their preferable engine, these
  +notes explain the difference between <CODE>mysql_use_result()</CODE> and
  +<CODE>mysql_store_result()</CODE>. The two influence the speed/size of the processes. <CODE>DBD::mysql</CODE> documentation includes the following (version 2.0217) snippet:
  +
  +<P>
  +<PRE>  mysql_use_result attribute: This forces the driver to use
  +  mysql_use_result rather than mysql_store_result. The former is
  +  faster and less memory consuming, but tends to block other
  +  processes. (That's why mysql_store_result is the default.)
  +</PRE>
  +<P>
  +Think about it in client/server terms. When you ask the server to
  +spoon-feed you the data as you use it, the server process must now buffer
  +the data and tie up that thread and possibly keep any database locks open
  +for a much longer time. So if you read a row of data, and ponder it for a
  +while, the tables you have locked are still locked, and the server is busy
  +talking to you every so often. That is
  +<CODE>mysql_use_result()</CODE>.
  +
  +<P>
  +If you just suck down the whole dataset to the client, then the server is
  +free to go about its business serving other requests. This results in
  +parallelism since the server and client are doing work at the same time,
  +rather than blocking on each other doing frequent I/O. That is
  +<CODE>mysql_store_result()</CODE>.
  +
  +<P>
  +As mysql manual suggests: you should not use <CODE>mysql_use_result()</CODE> if you are doing a lot of processing for each row on the client side. This
  +will tie up the server and prevent other threads from updating any tables
  +from which the data are fetched.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A></H1></CENTER>
  +<P>
   In this section you will find scripts, modules and code snippets to help
   get yourself started to use relational Databases with mod_perl scripts.
   Note that I work with <CODE>mysql</CODE> ( <A HREF="http://www.mysql.com">http://www.mysql.com</A> ), so the code
  @@ -275,7 +331,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A></H3></CENTER>
  +<CENTER><H2><A NAME="Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A></H2></CENTER>
   <P>
   Having to write many queries in my CGI scripts, made me to write a stand
   alone module that saves me a lot of time in writing and debugging my code.
  @@ -288,7 +344,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="My_DB_module">My::DB module</A></H3></CENTER>
  +<CENTER><H2><A NAME="My_DB_module">My::DB module</A></H2></CENTER>
   <P>
   (note that you will not find it on CPAN)
   
  @@ -916,14 +972,12 @@
     
     } # end of sub DESTROY
     
  -  
  -  
     # Don't remove
     1;
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A></H3></CENTER>
  +<CENTER><H2><A NAME="My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A></H2></CENTER>
   <P>
   In your code that wants to use <CODE>My::DB</CODE>, you have to create a
   <CODE>My::DB</CODE> object first:
  @@ -1110,7 +1164,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/05/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.3       +0 -0      modperl-site/guide/dbm.html
  
  Index: dbm.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/dbm.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- dbm.html	1999/05/17 20:47:32	1.2
  +++ dbm.html	1999/06/05 17:47:12	1.3
  @@ -247,7 +247,7 @@
     
     BEGIN {
         # RCS/CVS complient:  must be all one line, for MakeMaker
  -    $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
  +    $DB_File::Wrap::VERSION = do { my @r = (q$Revision: 1.3 $ =~ /\d+/g); sprintf &quot;%d.&quot;.&quot;%02d&quot; x $#r, @r };
     
     }
     
  
  
  
  1.12      +205 -27   modperl-site/guide/debug.html
  
  Index: debug.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/debug.html,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- debug.html	1999/05/08 17:46:29	1.11
  +++ debug.html	1999/06/05 17:47:13	1.12
  @@ -29,11 +29,15 @@
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  -	<LI><A HREF="#Sometimes_script_works_Sometime">Sometimes script works, Sometimes Not</A>
  +	<LI><A HREF="#Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A>
  +	<LI><A HREF="#Non_interactive_debugging_when_r">Non-interactive debugging when running under mod_perl</A>
   	<LI><A HREF="#Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A>
   	<LI><A HREF="#Debug_Tracing">Debug Tracing</A>
  -	<LI><A HREF="#Getting_some_decent_debug_info_w">Getting some decent debug info when running under mod_perl</A>
   	<LI><A HREF="#gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A>
  +	<LI><A HREF="#Monitoring_error_log_file">Monitoring error_log file</A>
  +	<LI><A HREF="#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
  +	<LI><A HREF="#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
  +	<LI><A HREF="#Devel_Peek">Devel::Peek</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -51,19 +55,39 @@
   
   	      <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <P>
  -<CENTER><H1><A NAME="Sometimes_script_works_Sometime">Sometimes script works, Sometimes Not</A></H1></CENTER>
  +<CENTER><H1><A NAME="Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A></H1></CENTER>
   <P>
  -See <A HREF="././porting.html#Sometimes_it_Works_Sometimes_Not">Sometimes it works Sometimes Not</A>
  +See <A HREF="././porting.html#Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it does Not</A>
   
   
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Non_interactive_debugging_when_r">Non-interactive debugging when running under mod_perl</A></H1></CENTER>
  +<P>
  +To debug scripts running under mod_perl either use <A HREF="././debug.html#Apache_DB_Run_the_interactive">Apache::DB (interactive Perl debugging)</A> or an older non-interactive method as described below.
  +
  +<P>
  +<CODE>NonStop</CODE> debugger option enables us to get some decent debug info when running under
  +mod_perl. For example, before starting the server:
  +
  +<P>
  +<PRE>  % setenv PERL5OPT -d
  +  % setenv PERLDB_OPTS &quot;NonStop=1 LineInfo=db.out AutoTrace=1 frame=2&quot;
  +</PRE>
  +<P>
  +Now watch db.out for line:filename info. This is most useful for tracking
  +those core dumps that normally leave us guessing, even with a stack trace
  +from gdb. db.out will show you what Perl code triggered the core. 'man
  +perldebug' for more PERLDB_OPTS. Note, Perl will ignore PERL5OPT if <CODE>PerlTaintCheck</CODE> is <CODE>On</CODE>.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A></H1></CENTER>
   <P>
   Perl ships with a very useful interactive debugger, however, it does not
  -run ``out-of-the-box'' in the Apache/mod_perl environment. Apache::DB makes
  -a few adjustments so the two will cooperate.
  +run ``out-of-the-box'' in the Apache/mod_perl environment.
  +<CODE>Apache::DB</CODE> makes a few adjustments so the two will cooperate.
   
   <P>
   To configure it use:
  @@ -78,12 +102,13 @@
     &lt;/Location&gt;
   </PRE>
   <P>
  -You must run the server in the single mode (with -X) to use Apache::DB.
  +You must run the server in the single mode (with -X) to use
  +<CODE>Apache::DB</CODE>.
   
   <P>
   When you run the script for the first time, you should let it run until it
   finishes. Starting from the second run you can run it as if it was a
  -regular perl script. 
  +regular perl script.
   
   <P>
   Module and Scripts that were preloaded and compiled during the server
  @@ -128,39 +153,192 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Getting_some_decent_debug_info_w">Getting some decent debug info when running under mod_perl</A></H1></CENTER>
  +<CENTER><H1><A NAME="gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A></H1></CENTER>
  +<P>
  +As you know you need an unstriped executable to be able to debug it. While
  +you can compile the mod_perl with <CODE>-g</CODE> (or <CODE>PERL_DEBUG=1</CODE>) the apache <CODE>install</CODE> strips the symbols.
  +
   <P>
  -As many of you know, the interactive Perl debugger does not run under
  -Apache/mod_perl (yet). However, Dean Gaudet made the discovery last night
  -of the NonStop option. This enables us to get some decent debug info when
  -running under mod_perl. For example, before starting the server:
  +Makefile.tmpl contains a line:
   
   <P>
  -<PRE>  % setenv PERL5OPT -d
  -  % setenv PERLDB_OPTS &quot;NonStop=1 LineInfo=db.out AutoTrace=1 frame=2&quot;
  +<PRE>  IFLAGS_PROGRAM  = -m 755 -s 
   </PRE>
   <P>
  -Now watch db.out for line:filename info. This is most useful for tracking
  -those core dumps that normally leave us guessing, even with a stack trace
  -from gdb. db.out will show you what Perl code triggered the core. 'man
  -perldebug' for more PERLDB_OPTS. Note, Perl will ignore PERL5OPT if <CODE>PerlTaintCheck</CODE> is <CODE>On</CODE>.
  +Removing the -s does the trick.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A></H1></CENTER>
  +<CENTER><H1><A NAME="Monitoring_error_log_file">Monitoring error_log file</A></H1></CENTER>
   <P>
  -As you know you need an unstriped executable to be able to debug it. While
  -you can compile the mod_perl with <CODE>-g</CODE> the apache
  -<CODE>install</CODE> strips the symbols.
  +As I have mentioned it before, <CODE>error_log</CODE> file is your best friend in CGI code debugging process. 
   
   <P>
  -Makefile.tmpl contains a line:
  +While debugging my mod_perl and general CGI code, I keep my
  +<CODE>error_log</CODE> file open in a dedicated terminal window (xterm), so I can see what
  +errors/warnings are being reported by server right away. I do it with:
   
   <P>
  -<PRE>  IFLAGS_PROGRAM  = -m 755 -s 
  +<PRE>  tail -f /usr/local/apache/logs/error_log
   </PRE>
   <P>
  -Removing the -s does the trick.
  +which shows all the lines that are being added to the file.
  +
  +<P>
  +If you cannot access your <CODE>error_log</CODE> file because you are unable to telnet to your machine (generally a case
  +with some ISPs who provides user CGI support but no telnet access), you
  +might want to use a CGI script I wrote to fetch the latest lines from the
  +file (with a bonus of colored output for an easier reading). You might need
  +to ask your ISP to install this script for a general usage. See <A HREF="././snippets.html#Watching_the_error_log_file_with">Watching the error_log file without telneting to the server.</A>
  +
  +
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A></H1></CENTER>
  +<P>
  +Current perl implementation does not restore the original apache's C
  +handler when you use <CODE>local $SIG{FOO}</CODE> clause. While save/restore of
  +<CODE>$SIG{ALRM}</CODE> was fixed in the mod_perl 1.19_01 (CVS version) other signals are not yet
  +fixed. The real fix should probably be in Perl itself.
  +
  +<P>
  +Untill recent <CODE>local $SIG{ALRM}</CODE> restored the <CODE>SIGALRM</CODE> handler to Perl's handler, not the handler it was in the first place
  +(apache's
  +<CODE>alrm_handler()</CODE>). if you build mod_perl with <CODE>PERL_TRACE=1</CODE> and set the <CODE>MOD_PERL_TRACE</CODE> environment variable to <STRONG>g</STRONG>, you will see this in the <CODE>error_log</CODE> file:
  +
  +<P>
  +<PRE>  mod_perl: saving SIGALRM (14) handler 0x80b1ff0
  +  mod_perl: restoring SIGALRM (14) handler from: 0x0 to: 0x80b1ff0
  +</PRE>
  +<P>
  +If nobody touched <CODE>$SIG{ALRM}</CODE>, <CODE>0x0</CODE> would be the same address as the others.
  +
  +<P>
  +If you work with signal handlers take a look at <CODE>Sys::Signal</CODE> module, which solves the problem:
  +
  +<P>
  +<CODE>Sys::Signal</CODE> - Set signal handlers with restoration of existing C sighandler. Get it
  +from the CPAN.
  +
  +<P>
  +The usage is simple, if the original code was:
  +
  +<P>
  +<PRE>  eval {
  +    local $SIG{ALRM} = sub { die &quot;timeout\n&quot; };
  +    alarm $timeout;
  +    ... db stuff ...
  +    alarm 0;
  +  };
  +   
  +  die $@ if $@;
  +</PRE>
  +<P>
  +Now you would write:
  +
  +<P>
  +<PRE>  use Sys::Signal ();
  +  eval {
  +    my $h = Sys::Signal-&gt;set(ALRM =&gt; sub { die &quot;timeout\n&quot; });
  +    alarm $timeout;
  +    ... do something thay may timeout ...
  +      alarm 0;
  +  };
  +  die $@ if $@;
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="examples_of_strace_or_truss_us">examples of strace (or truss) usage</A></H1></CENTER>
  +<P>
  +(META: below are some snippets of strace outputs from list's emails)
  +
  +<P>
  +[there was a talk about Streaming LWP through mod_perl and the topic was
  +suggested optimal buffer size]
  +
  +<P>
  +Optimal buffer size depends on your system configuration, watch apache with <CODE>strace -p</CODE> (or <CODE>truss</CODE>) when its sending a static file, here perlfunc.pod on my laptop (linux
  +2.2.7):
  +
  +<P>
  +<PRE>  writev(4, [{&quot;HTTP/1.1 200 OK\r\nDate: Wed, 02&quot;..., 289}, {&quot;=head1
  +  NAME\n\nperlfunc - Perl b&quot;..., 32768}], 2) = 33057
  +  alarm(300)                              = 300
  +  write(4, &quot;m.  In older versions of Perl, i&quot;..., 32768) = 32768
  +  alarm(300)                              = 300
  +  write(4, &quot;hout waiting for the user to hit&quot;..., 32768) = 32768
  +  alarm(300)                              = 300
  +  write(4, &quot;&gt;&amp;STDOUT&quot;) || die &quot;Can't dup &quot;..., 32768) = 32768
  +  alarm(300)                              = 300
  +  write(4, &quot;LEHANDLE is supplied.  This has &quot;..., 32768) = 32768
  +  alarm(300)                              = 300
  +  write(4, &quot;ite&gt;,\nC&lt;seek&gt;, C&lt;tell&gt;, or C&lt;eo&quot;..., 25657) = 25657
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Devel_Peek">Devel::Peek</A></H1></CENTER>
  +<P>
  +Devel::Peek - A data debugging tool for the XS programmer
  +
  +<P>
  +Let's see an example of Perl allocating buffer size only once, regardless
  +of <CODE>my()</CODE> scoping, although it will realloc if the size is &gt;
  +SvLEN:
  +
  +<P>
  +<PRE>  use Devel::Peek;
  +  
  +  for (1..3) {
  +      foo();
  +  }
  +  
  +  sub foo {
  +      my $sv;
  +      Dump $sv;
  +      $sv = 'x' x 100_000;
  +      $sv = &quot;&quot;;
  +  }
  +</PRE>
  +<P>
  +The output:
  +
  +<P>
  +<PRE>  SV = NULL(0x0) at 0x8138008
  +    REFCNT = 1
  +    FLAGS = (PADBUSY,PADMY)
  +  SV = PV(0x80e5794) at 0x8138008
  +    REFCNT = 1
  +    FLAGS = (PADBUSY,PADMY)
  +    PV = 0x815f808 &quot;&quot;\0
  +    CUR = 0
  +    LEN = 100001
  +  SV = PV(0x80e5794) at 0x8138008
  +    REFCNT = 1
  +    FLAGS = (PADBUSY,PADMY)
  +    PV = 0x815f808 &quot;&quot;\0
  +    CUR = 0
  +</PRE>
  +<P>
  +We can see that on subsequent calls (after the first one) <CODE>$sv</CODE>
  +already has a preallocated memory.
  +
  +<P>
  +so, if you can afford the memory, the larger the buffer means less
  +<CODE>brk()</CODE> syscalls. if you watch that example with strace, you will only see calls to <CODE>brk()</CODE> in the first time through the loop. So, this is a case where you module
  +might want to pre-allocate the buffer for example for LWP, a file scope
  +lexical, like so:
  +
  +<P>
  +<PRE>  package Your::Proxy;
  +  
  +  my $buffer = ' ' x 100_000;
  +  $buffer = &quot;&quot;;
  +</PRE>
  +<P>
  +This way, only the parent has to <CODE>brk()</CODE> at server startup, each
  +child already will already have an allocated buffer, just reset to ``'',
  +when you are done.
   
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -185,7 +363,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/05/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.6       +685 -641  modperl-site/guide/guide-src.tar.gz
  
  	<<Binary file>>
  
  
  1.7       +1294 -1180modperl-site/guide/guide.tar.gz
  
  	<<Binary file>>
  
  
  1.2       +195 -173  modperl-site/guide/hardware.html
  
  Index: hardware.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/hardware.html,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- hardware.html	1999/05/17 20:47:35	1.1
  +++ hardware.html	1999/06/05 17:47:17	1.2
  @@ -1,7 +1,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Choosing an Operating System and a Hardware</TITLE>
  +   <TITLE>mod_perl guide: Choosing an Operating System and Hardware</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -23,14 +23,14 @@
   <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 an Operating System and a Hardware</H1>
  +Choosing an Operating System and Hardware</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="obvious.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="snippets.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="advocacy.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
   	<LI><A HREF="#Is_it_important_">Is it important?</A>
  -	<LI><A HREF="#Operating_System_Choosing">Operating System Choosing</A>
  +	<LI><A HREF="#Choosing_an_Operating_System">Choosing an Operating System</A>
   	<UL>
   
   		<LI><A HREF="#Stability_and_Robustness">Stability and Robustness</A>
  @@ -42,12 +42,11 @@
   		<LI><A HREF="#OS_Releases">OS Releases</A>
   	</UL>
   
  -	<LI><A HREF="#Hardware_Choosing">Hardware Choosing</A>
  +	<LI><A HREF="#Choosing_Hardware">Choosing Hardware</A>
   	<UL>
   
  -		<LI><A HREF="#Site_s_traffic">Site's traffic</A>
  +		<LI><A HREF="#Site_traffic">Site traffic</A>
   		<LI><A HREF="#Cash">Cash</A>
  -		<LI><A HREF="#IO_performance">IO performance</A>
   		<LI><A HREF="#Memory">Memory</A>
   		<LI><A HREF="#Internet_Connection">Internet Connection</A>
   		<LI><A HREF="#Bottlenecks">Bottlenecks</A>
  @@ -73,32 +72,33 @@
   <P>
   <CENTER><H1><A NAME="Is_it_important_">Is it important?</A></H1></CENTER>
   <P>
  -You can invest a lot of time and money into a server tuning and code
  -rewriting according the guidelines you have just learned, but your
  -performance will be really bad if you did not took into account the
  -hardware demands, and did not wisely chosen the operational system suited
  -for your needs. While tips below apply to any webserver, they are written
  -for a mod_perl enabled webservers' administrators.
  +You can invest a lot of time and money in server tuning and code rewriting
  +according the guidelines you have just learned, but your performance will
  +be really bad if you did not take into account the hardware demands, and
  +did not wisely chose the operating system suited for your needs. While the
  +tips below apply to any webserver, they are written for a mod_perl enabled
  +webservers' administrators.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Operating_System_Choosing">Operating System Choosing</A></H1></CENTER>
  +<CENTER><H1><A NAME="Choosing_an_Operating_System">Choosing an Operating System</A></H1></CENTER>
   <P>
   First lets talk about Operating Systems (OS). While personally I am a Linux
   devotee, I do not want to start yet another OS war. Assuming this, I will
   try to define what you should be looking for, then when you know what do
  -you want from your to be chosen OS, go find it. Enter the newsgroup of an
  -OS you think is a good candidate, and tell: ``I need an OS with good X,
  -fast Y and stable Z, do you think Foo OS answers all of my demands?'' I
  -will leave this fan research up to you. But I would use linux :) Just
  -kidding...
  +you want from your OS, go find it. Visit the Web sites of operating systems
  +you are interested in. You can gauge user's opinions by searching relevant
  +discussions in newsgroup and mailing list archives such as Deja - <A
  +HREF="http://deja.com">http://deja.com</A> and eGroups - <A
  +HREF="http://egroups.com">http://egroups.com</A> . I will leave this fan
  +research up to you. But I would use linux :o) Just kidding...
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Stability_and_Robustness">Stability and Robustness</A></H2></CENTER>
   <P>
  -Probably the most important feature we want from OS is its stability and
  -robustness. We are into an Internet business, which does not have working
  +Probably the most desired features in an OS are stability and robustness.
  +We are involved in an Internet business, which does not have normal working
   hours, like many conventional businesses we know about (9pm to 5pm). We are
   open 24 hours a day. We can not afford off line periods, for our customers
   will go shop for another service like ours, unless you have a monopoly :) .
  @@ -112,30 +112,30 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Memory_Management">Memory Management</A></H2></CENTER>
   <P>
  -You want an OS with good memory management, for some OSes are well known as
  -memory hogs. The same code can use as twice as much memory on one OS
  -compared to the other. If the size of the mod_perl process is 10Mb and you
  -have tens of these running, it definitely adds up!
  +You want an OS with a good memory management, some OSes are well known as
  +memory hogs. The same code can use twice as much memory on one OS compared
  +to the other. If the size of the mod_perl process is 10Mb and you have tens
  +of these running, it definitely adds up!
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Memory_Leakages">Memory Leakages</A></H2></CENTER>
   <P>
  -Some OSes and/or the libraries (like c libs) suffer from bad memory
  -leakages. You cannot afford such a system, for you are already know that a
  -single mod_perl process sometimes serves thousands of requests before it is
  -being put to death. So if the leaks add up on every request, your memory
  -demands will be huge. Of course your code can be guilty for the memory
  -leakages as well (check out the <CODE>Apache::Leak</CODE>
  +Some OSes and/or the libraries (like C libraries) suffer from memory
  +leakage. You cannot afford such a system, for you are already know that a
  +single mod_perl process sometimes serves thousands of requests before it
  +terminates. So if a leak occurs on every request, your memory demands will
  +be huge. Of course your code can be the cause of the memory leakages as
  +well (check out the <CODE>Apache::Leak</CODE>
   module). Certainly you can lower the number of requests to be served over
  -the process' life, but a performance degrade.
  +the process' life, but performance degrades with this.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Sharing_Memory">Sharing Memory</A></H2></CENTER>
   <P>
  -You want an OS with good sharing capabilities. As you have learned, if you
  -preload the modules and scripts at the server startup, they are being
  +You want an OS with good memory sharing capabilities. As you have learned,
  +if you preload the modules and scripts at server startup, they are being
   shared between the spawned children, at least for a part of a process' life
   span, since memory pages are getting ``dirty'' and ceasing to be shared.
   This feature can save you up a lot of memory!!!
  @@ -144,86 +144,92 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Cost_and_Support">Cost and Support</A></H2></CENTER>
   <P>
  -If you are into a big business you are not overly concerned about paying
  -$1000+ for some fancy OS and to get the bundled support for it. But if your
  -resources are low, you will look for a cheaper and free OSes. Free does not
  -mean bad, it can be quite the opposite as we all either know from our own
  -experience or read about in news. Free OSes can have and do have the best
  -support you can find. It is very easy to understand - most of the people
  -are not rich and will try to use a cheaper or free OS first if it does the
  -work for them. Since it really fits their needs, many people keep using it
  -and eventually know it quite good to provide a support for others in
  -trouble. Why would they do it for free? For a real spirit of the first days
  -of the Internet, when there was no commercial Internet and people helped
  -each other, because someone helped them in first place. I was there, I was
  -touched by that spirit and I will do anything to keep this spirit alive.
  +If you are into a big business you are probably do not care to pay another
  +<CODE>$1000</CODE> for some fancy OS and to get the bundled support for it.
  +But if your resources are low, you will look for cheaper and free OSes.
  +Free does not mean bad, it can be quite opposite as we all either know from
  +our own experience or read about in news. Free OSes could have and do have
  +the best support you can find. It is very easy to understand - most of the
  +people are not rich and will try to use a cheaper or free OS first if it
  +does the work for them. Since it really fits their needs, many people keep
  +using it and eventually know it well enough to be able to provide support
  +for others in trouble. Why would they do this for free? For a real spirit
  +of the first days of the Internet, when there was no commercial Internet
  +and people helped each other, because someone helped them in first place. I
  +was there, I was touched by that spirit and I will do anything to keep this
  +spirit alive.
   
   <P>
  -But, lets back to our world. We are living in a material world, and our
  +But, let's get back to our world. We are living in material world, and our
   bosses pay us to keep the systems running. So if you feel that you cannot
   provide the support yourself and you do not trust the available free
  -resources, you must get an OS that have behind a company to pay for, and to
  -blame for any difficulties you might experience in hope that your cries for
  -help will be heard and answered. Your boss wants to be able to sue someone
  -if the project has a problem. If you buy a product and the company claims
  -support, then you have someone to sue. You do not have someone to sue other
  -than getting fired yourself if you go with Open Source and it fails.
  +resources, you must get an OS that has a company behind it to pay to blame
  +for any problems you encounter in hopes that your cries for help will be
  +heard and answered. Your boss wants to be able to sue someone if the
  +project has a problem caused by the external product that is being used in
  +the project. If you buy a product and the company selling it, claims
  +support, you have someone to sue. You do not have someone to sue other than
  +getting yourself fired if you go with Open Source and it fails.
   
   <P>
  +Also remember that if you spend less or zero money on OS and Software, you
  +will be able to buy a better and stronger hardware.
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Discontinued_products">Discontinued products</A></H2></CENTER>
   <P>
   You have invested a lot into a developing of some proprietary software,
  -that is bundled with the OS you were developing on and for. For example you
  -write some mod_perl handler that takes an advantage of some proprietary
  -features of the OS which make it faster and it will not run on any other
  -OS. Things are under control, the performance is great and you sing from
  -happiness. But... one day the company who wrote your beloved OS went
  -bankrupt, which is not unlikely to happen nowadays. You have got stuck with
  -their last masterpiece and no support! What are you going to do then?
  -Invest more into a porting of the software to another OS...
  +that is bundled with the OS you were developing on and for. Like you write
  +some mod_perl handler that takes an advantage of some proprietary features
  +of the OS and it will not run on any other OS. Things are under control,
  +the performance is great and you sing from happiness. But... one day the
  +company who wrote your beloved OS went bankrupt, which is not unlikely to
  +happen nowadays. You have got stuck with their last masterpiece and no
  +support! What you are going to do then? Invest more into porting the
  +software for another OS...
   
   <P>
   Everyone can be hit by this mini disaster, so it is better to watch the
   background of the company when making your choice, but still you never know
  -what will happen in the next minute. The OSes in this hazard group are
  -developed completely by a single companies. Free OSes are probably more
  -promising for a development is distributed between many companies and
  -developers, so if a person who developed a really important part of the
  -kernel lost an interest to continue, someone else will pick up the falling
  -flag and continue from the same place. Of course if tomorrow some better
  -project will show up, developers might migrate there and finally drop the
  -development, but we are here not to let this happen.
  +what will happen in a next minute. The OSes in this hazard group are
  +completely developed by a single companies. Free OSes are probably less
  +susceptible to this, for development is distributed between many companies
  +and developers, so if a person who developed a really important part of the
  +kernel lost interest to continue, someone else will pick the falling flag
  +and continue from the same place. Of course if tomorrow some better project
  +shows up, developers might migrate there and finally drop the development,
  +but we are here not to let this happen.
   
   <P>
  -But you are the one responsible for making the right decision...
  +But you are the one to make the right decision...
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="OS_Releases">OS Releases</A></H2></CENTER>
   <P>
  -Actively developed OSes are generally tries to keep the pace with the
  -latest technology developments, and all the time optimize the kernel and
  -other parts of OS to become better and faster. Nowadays, Internet and
  -Networking in general are the most hot targets for system developers.
  -Sometimes a simple OS upgrade to a latest stable version, can save you an
  -expensive hardware upgrade. Also, remember that when you buy a new
  -hardware, chances are that latest software will take the most out of it.
  -Since while the existent software (drivers) might support the new product
  -because of its back compatibility with previous products of the same family
  -(brand), it might not take benefits of new features, so the you could spend
  -much less money for the same functionality if you were to buy a previous
  -model of the same product.
  +Actively developed OSes generally try to keep the pace with the latest
  +technology developments, and continually optimize the kernel and other
  +parts of OS to become better and faster. Nowadays, Internet and Networking
  +in general are the hottest targets for system developers. Sometimes a
  +simple OS upgrade to a latest stable version, can save you an expensive
  +hardware upgrade. Also, remember that when you buy a new hardware, chances
  +are that the latest software will make the most out of it. Since while the
  +existing software (drivers) might support the new brand product because of
  +its back compatibility with previous products of the same family, it might
  +not take advantage of new features. It means that you could spend much less
  +money for almost the same functionality if you were to buy a previous model
  +of the same product.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Hardware_Choosing">Hardware Choosing</A></H1></CENTER>
  -<P>
  -While I am not fond of the idea of updating this section of the mod_perl
  -guide every day a new processor or memory type comes out, exactly like with
  -OS choosing guidelines, I will only hint what should you look for and
  -persuade you that sometimes the most expensive machine is not the one which
  -provides the best performance.
  +<CENTER><H1><A NAME="Choosing_Hardware">Choosing Hardware</A></H1></CENTER>
  +<P>
  +While I am not fond of the idea of updating this section every day a new
  +processor or memory type comes out, exactly like with OS choosing
  +guidelines, I will only hint what should you look after and persuade you
  +that sometimes the most expensive machine is not the one which provides the
  +best performance.
   
   <P>
   Your demands are bound to many aspects and components. Let's discuss some
  @@ -267,13 +273,13 @@
   </UL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Site_s_traffic">Site's traffic</A></H2></CENTER>
  +<CENTER><H2><A NAME="Site_traffic">Site traffic</A></H2></CENTER>
   <P>
  -If you are building a fans' site but want to amaze your friends with
  -mod_perl guest book, an old 486 machine will do. If you are into a serious
  -business, it is very important to build a scalable server, so if your
  -service is successful and becomes popular, you get your server's traffic
  -doubled every few days, you should be ready to add more resources
  +If you are building a fans' site, but want to amaze your friends with
  +mod_perl guest book, an old 486 machine will do it. If you are into a
  +serious business, it is very important to build a scalable server, so if
  +your service is successful and becomes popular, you get your server's
  +traffic doubled every few days, you should be ready to add more resources
   dynamically. While we can define the webserver scalability more precisely,
   the important thing is to make sure that you can add more power to your
   <CODE>webserver(s)</CODE> without investing additional money into a
  @@ -296,91 +302,92 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Cash">Cash</A></H2></CENTER>
   <P>
  -Everybody knows that Internet is a big cash hole, whatever you throw in,
  -hardly ever comes back. This is not always correct, but there is a lot of
  -wisdom in these words. While you have to invest money to build a decent
  -service, it can be cheaper! You can spend as much as 10 times more money on
  -a new strong machine, but to get only a 10% improvement in performance.
  -Remember that processor that was born 4 years ago is still very mighty.
  +Everybody knows that Internet is a cash hole, what you throw in, hardly
  +comes back. This is not always correct, but there is a lot of wisdom in
  +these words. While you have to invest money to build a decent service, it
  +can be cheaper! You can spend as much as 10 times more money on a strong
  +new machine, but get only a 10% improve in performance. Remember that
  +processor that was born 4 years ago is still very mighty.
   
   <P>
  -If you really need a lot of power do not think about a strong machine
  -(unless you have money to throw away), think about clustering and load
  -balancing. You can probably buy 10 times more older but very cheap machines
  -and have a 8 times more power, then purchasing only one single newest
  +If you really need a lot of power do not think about a single strong
  +machine (unless you have money to throw away), think about clustering and
  +load balancing. You can probably buy 10 times more older but very cheap
  +machines and have a 8 times more power, then purchasing only one single new
   machine. Why is that? Because as I mentioned before generally the
  -performance improve is very marginal while the price is much bigger.
  -Because 10 machines will do a faster Hard Disk IO (Input/Output), then one
  -single machine even if the disk is much faster. Yes, you have more
  -administration overhead, but there is a chance you will have it anyway, for
  -in a short time the machine you have just invested into will not stand the
  -load and you will have to purchase more and to think how to implement the
  -load balancing and file system distribution.
  +performance improvement is marginal while the price is much bigger. Because
  +10 machines will do a faster Hard Disk IO (Input/Output), then one single
  +machine even if the disk is much faster. Yes, you have more administration
  +overhead, but there is a chance you will have it anyway, for in a short
  +time the machine you have just invested into will not stand the load and
  +you will have to purchase more and think how to implement the load
  +balancing and file system distribution.
   
   <P>
   Why I am so convinced? Facts! Look at the most used services on the
   Internet: search engines, email servers and alike - most of them are using
  -the clustering approach. While you are not always notice that, they do it
  -by hiding the real implementation behind the proxy servers.
  +clustering approach. While you will not always notice that, they do it by
  +hiding the real implementation behind the proxy servers.
   
   <P>
  -<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="IO_performance">IO performance</A></H2></CENTER>
  +<PRE> =head2 IO performance
  +</PRE>
   <P>
   If your service is IO bound (does a lot of read/write operations to your
   disk, remember that relational DataBases are sitting on disk as well) you
  -need a very fast disk. So you should not spend money on Video card and
  +need a very fast disk. So you should not spend money on a Video card and
   monitor (monochrome card and 14`` B&amp;W will do for server
  -configuration), but to look for the best price/performance disks. Of course
  -you should ask around for a solid firm, whose HDs are not getting corrupted
  -at all. With money in hand you should think about getting a RAID system
  -(RAID is generally a box with many HDs, and it capable to read/write data
  -much faster. and is protected against disk corruptions, for it duplicates
  -the same data over a number of disks, so if one gets corrupted RAID detects
  -it and data is still correct on the duplicated disks.) You must think about
  -RAID or alike systems if you have an enormous data size to serve. (What is
  -enormous data size nowadays?).
  +configuration), but rather look for the best price/performance in disks (of
  +course asking around for a solid firm, whose HDs are not getting corrupted
  +at all.) With money in hand you should think about getting a RAID system.
  +RAID is generally a box with many HDs. It is capable of reading/writing
  +data much faster, and is protected against disk corruptions. It does this
  +by duplicating the same data over a number of disks, so if one gets
  +corrupted the RAID detects it and the data is still correct on the
  +duplicated disks. You must think about RAID or similar systems if you have
  +an enormous data set to serve. (What is an enormous data set nowadays?).
   
   <P>
   Ok, we have a fast disk, what's next? You need a fast disk controller. So
  -ether you should use the one coming on your motherboard or you should plug
  -a controller card if the one you have onboard is not good enough.
  +either you should use the one embedded on your motherboard or you should
  +plug a controller card if the one you have onboard is not good enough.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Memory">Memory</A></H2></CENTER>
   <P>
  -How much RAM do you need? Nowadays, most chances you will hear: ``Memory is
  -cheap, the more you buy the better''. But how much is enough? The answer
  -pretty straightforward: ``You do not want your machine to swap''. When CPU
  -needs to write something into a memory, but notices that it is already
  -full, it takes the least frequently used memory pages (4k/page on average
  -OS) and swap them out. Swapping out, means copying to the disk into a
  -special partition or file called swap and deleting from the real memory.
  -The another process asks CPU to bring another page, but CPU cannot find a
  -memory page in the RAM, it was just swapped out, so it goes and brings it
  -from the swap (swapping in). If memory is small, the swapping (in/out)
  -happens too frequently, CPU becomes too busy to bring the pages in and out,
  -HD working hard to read write the swapped out pages, and the whole
  -performance is going down. Sometimes your swap partition can become full as
  -well and your system might die.
  +How much RAM (Randomly Accessed Memory) do you need? Nowadays, chances are
  +you will hear: ``Memory is cheap, the more you buy the better''. But how
  +much is enough? The answer pretty straightforward: ``You do not want your
  +machine to swap''. When the CPU needs to write something into memory, but
  +notices that it is already full, it takes the least frequently used memory
  +pages (4k/page on average OS) and swaps them out. Swapping out means
  +copying to the disk into a special partition or file called swap and
  +deleting from the real memory. When another process asks the CPU to access
  +another page, but CPU cannot find the memory page in RAM (it was just
  +swapped out), it goes and brings it from the swap (swapping in). If memory
  +is small, swapping (in/out) happens too frequently, the CPU becomes too
  +busy swapping pages in and out, the HD is working hard to read/write the
  +swapped out pages, and the whole performance of the system is going down.
  +Sometimes your swap partition can become full as well and your system might
  +die.
   
   <P>
   How do you make a decision? You know what is the highest page request rate
  -your service has and how long does an average request processing take. Now
  -you can calculate how many servers do you need. Knowing the how big any of
  +your service has and how much time an average request takes. Now you can
  +calculate how many servers do you need. Knowing the maximum size any of
   your servers can get, you know how much memory do you need. You probably
   need less memory that you have calculated if your OS supports memory
   sharing and you know how to deploy this feature (preloading the modules and
  -scripts at server's startup). Do not forget that other essential system's
  +scripts at server's startup). Do not forget that other essential system
   processes need memory as well, so you should not plan for the webserver
   only, but to take into an account all processes to be run on your system.
  -Remember that requests can be queued, so if you can afford your client to
  -wait a few moments, while some process gets free to serve it, your numbers
  -will be more correct, since you generally do not have the highest load, but
  -you should be ready to bear the picks. So you need to reserve at least 20%
  -of free memory for a pick situations. Many sites were reported to crash a
  -few moments after some scooping news about them were posted, and unexpected
  +Remember that requests can be queued, so you can afford your client to wait
  +a few moments, while some server comes to service it, your numbers will be
  +more correct, since you generally do not have the highest load, but you
  +should be ready to bear the picks. So you need to reserve at least 20% of
  +free memory for peak situations. Many sites were reported to crash a few
  +moments after some scooping news about them were posted, and unexpected
   number of requests suddenly came in. If you are about to announce something
   cool, be aware of possible consequences.
   
  @@ -391,41 +398,56 @@
   You have the best hardware you could get, but the service is still
   crawling. Make sure you have a fast Internet connection. Not _fast_ as your
   ISP claims it to be, but fast as it should be. The ISP might have a very
  -good connection to the Internet, but to put many clients on the same line,
  -and if these are heavy clients your traffic will have to share the same
  -line, thus the speed is getting down. Think about dedicated connection and
  +good connection to the Internet, but put many clients on the same line. If
  +these are heavy clients your traffic will have to share the same line, thus
  +your speed is effectively limited. Think about a dedicated connection and
   make sure it is truly dedicated, trust the ISP but check it!
   
   <P>
  +The idea of having a connection to <STRONG>The Internet</STRONG> is a little misleading. Many Web hosting and co-location companies have
  +large amounts of bandwidth, but still have poor connectivity. The public
  +exchanges, such as MAE-East and MAE-West, frequently become overloaded, yet
  +many ISPs depend on these exchanges.
  +
  +<P>
  +Private peering means that providers can exchange traffic much quicker.
  +
  +<P>
  +Also, if your Web site is of global interest, check that the ISP has good
  +global connectivity. If the Web site is going to be visited mostly by
  +people in a certain country or region, your server should probably be
  +located there.
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Bottlenecks">Bottlenecks</A></H2></CENTER>
   <P>
   The most important thing to understand is that you might use the most
  -expensive components, but still get bad performance. Why? Let me introduce
  -you to this annoying term: A bottleneck.
  +expensive components, but still get a bad performance. Why? Let me
  +introduce you to this annoying word: A bottleneck.
   
   <P>
  -A machine is an aggregate of are many small and big components. Each one of
  -them can become a bottleneck. If you have a fast processor but not a great
  -deal of RAM, the processor will be under used waiting for the kernel to
  -swap in and out the memory pages, because memory is too small to fit at
  -least the most used ones. If you have a lot of memory and a fast processor
  -and a fast disk, but a slow controller - the performance will be poor, and
  -you will have wasted the money.
  +A machine is an aggregate of many small and big components. Each one of
  +them can become a bottleneck. If you have a fast processor but a small
  +amount of RAM (memory), the processor will be under utilized waiting for
  +the kernel to swap memory pages in and out, because memory is too small to
  +fit at least the most used ones. If you have a lot of memory and a fast
  +processor and a fast disk, but a slow controller - the performance will be
  +bad, and you have wasted the money.
   
   <P>
  -Of course use a NIC that does not create a bottleneck. If the NIC is slow,
  -the whole service is slow.
  +Of course use a NIC (Network Interface Card) that does not create a
  +bottleneck. If it is slow, the whole service is slow.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Conclusion">Conclusion</A></H2></CENTER>
   <P>
  -To use your money optimally, you have either to understand your hardware
  -very well, so you will know what to pick or you should hire a knowledgeable
  -hardware consultant or employee it on a constant basis, since your demands
  -are probably being changed as time goes, and your HW should be adopted to
  -every change you do.
  +To optimally use your money, you have to either understand the hardware
  +very well, so you will know what to pick, or you should hire a
  +knowledgeable hardware consultants and employ them on a constant basis,
  +since your demands will probably change as time goes on, and your HW should
  +be adapted with each change you make.
   
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -437,7 +459,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="performance.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="obvious.html">Next</A>      ]
  +	     [    <A HREF="snippets.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="advocacy.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -450,7 +472,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/04/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.13      +2 -2      modperl-site/guide/help.html
  
  Index: help.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/help.html,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- help.html	1999/05/17 20:47:36	1.12
  +++ help.html	1999/06/05 17:47:18	1.13
  @@ -25,7 +25,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>
   Getting Helped and Further Learning</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="snippets.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="download.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="advocacy.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="download.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  @@ -331,7 +331,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="snippets.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="download.html">Next</A>      ]
  +	     [    <A HREF="advocacy.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="download.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  
  
  
  1.16      +82 -61    modperl-site/guide/index.html
  
  Index: index.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/index.html,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- index.html	1999/05/17 20:47:36	1.15
  +++ index.html	1999/06/05 17:47:19	1.16
  @@ -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.11
  - May, 17 1999</B></P></CENTER>
  +<CENTER><P><B>Version 1.12
  + Jun, 5 1999</B></P></CENTER>
    
   <P>
   <HR WIDTH="100%"></P>
  @@ -54,13 +54,13 @@
   
   	<LI><A HREF="start.html#What_s_inside_">What's inside?</A>
   </UL>
  -<P><LI><A HREF="strategy.html"><B><FONT SIZE=+1>Picking the Right Strategy</FONT></B></A></LI><P>
  +<P><LI><A HREF="strategy.html"><B><FONT SIZE=+1>Choosing the Right Strategy</FONT></B></A></LI><P>
   <UL>
   
   	<LI><A HREF="strategy.html#Do_it_like_me_">Do it like me?!</A>
  -	<LI><A HREF="strategy.html#mod_perl_Deploying_Schemas_Overv">mod_perl Deploying Schemas Overview</A>
  +	<LI><A HREF="strategy.html#mod_perl_Deployment_Overview">mod_perl Deployment Overview</A>
   	<LI><A HREF="strategy.html#Standalone_mod_perl_Enabled_Apac">Standalone mod_perl Enabled Apache Server</A>
  -	<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_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>
  @@ -122,8 +122,11 @@
   	<UL>
   
   		<LI><A HREF="install.html#make_test_fails">make test fails</A>
  +		<LI><A HREF="install.html#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A>
  +		<LI><A HREF="install.html#Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A>
   	</UL>
   
  +	<LI><A HREF="install.html#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
   </UL>
   <P><LI><A HREF="config.html"><B><FONT SIZE=+1>Server Configuration</FONT></B></A></LI><P>
   <UL>
  @@ -142,6 +145,8 @@
   			<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>
   
   	</UL>
  @@ -158,12 +163,13 @@
   		<LI><A HREF="config.html#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="config.html#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="config.html#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="config.html#Is_there_a_way_to_modify_INC_on">Is there a way to modify @INC on a per-virtual-host basis. </A>
  +		<LI><A HREF="config.html#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="config.html#Sometimes_the_script_from_one_vi">Sometimes the script from one virtual host calls a script with</A>
   		<LI><A HREF="config.html#the_server_no_longer_retrieves_t">the server no longer retrieves the DirectoryIndex files for a directory</A>
   	</UL>
   
   	<LI><A HREF="config.html#Configuration_Security_Concerns">Configuration Security Concerns</A>
  +	<LI><A HREF="config.html#Logical_grouping_of_Location_Di">Logical grouping of Location, Directory and FilesMatch directives</A>
   </UL>
   <P><LI><A HREF="frequent.html"><B><FONT SIZE=+1>Frequent mod_perl problems</FONT></B></A></LI><P>
   <UL>
  @@ -210,7 +216,7 @@
   	<LI><A HREF="porting.html#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
   	<UL>
   
  -		<LI><A HREF="porting.html#Sometimes_it_Works_Sometimes_Not">Sometimes it Works Sometimes Not (Very important!)</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>
   	</UL>
  @@ -262,36 +268,8 @@
   	<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#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="hardware.html"><B><FONT SIZE=+1>Choosing an Operating System and a Hardware</FONT></B></A></LI><P>
  -<UL>
  -
  -	<LI><A HREF="hardware.html#Is_it_important_">Is it important?</A>
  -	<LI><A HREF="hardware.html#Operating_System_Choosing">Operating System Choosing</A>
  -	<UL>
  -
  -		<LI><A HREF="hardware.html#Stability_and_Robustness">Stability and Robustness</A>
  -		<LI><A HREF="hardware.html#Memory_Management">Memory Management</A>
  -		<LI><A HREF="hardware.html#Memory_Leakages">Memory Leakages</A>
  -		<LI><A HREF="hardware.html#Sharing_Memory">Sharing Memory</A>
  -		<LI><A HREF="hardware.html#Cost_and_Support">Cost and Support</A>
  -		<LI><A HREF="hardware.html#Discontinued_products">Discontinued products</A>
  -		<LI><A HREF="hardware.html#OS_Releases">OS Releases</A>
  -	</UL>
  -
  -	<LI><A HREF="hardware.html#Hardware_Choosing">Hardware Choosing</A>
  -	<UL>
  -
  -		<LI><A HREF="hardware.html#Site_s_traffic">Site's traffic</A>
  -		<LI><A HREF="hardware.html#Cash">Cash</A>
  -		<LI><A HREF="hardware.html#IO_performance">IO performance</A>
  -		<LI><A HREF="hardware.html#Memory">Memory</A>
  -		<LI><A HREF="hardware.html#Internet_Connection">Internet Connection</A>
  -		<LI><A HREF="hardware.html#Bottlenecks">Bottlenecks</A>
  -		<LI><A HREF="hardware.html#Conclusion">Conclusion</A>
  -	</UL>
  -
  -</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>
   
  @@ -302,6 +280,7 @@
   		<LI><A HREF="obvious.html#The_poison">The poison</A>
   		<LI><A HREF="obvious.html#The_diagnosis">The diagnosis</A>
   		<LI><A HREF="obvious.html#The_remedy">The remedy</A>
  +		<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>
  @@ -316,11 +295,11 @@
   	<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>
   	<LI><A HREF="obvious.html#Handling_the_User_pressed_Stop_">Handling the 'User pressed Stop button' case</A>
  -	<LI><A HREF="obvious.html#Handling_the_server_timeout_case">Handling the server timeout cases</A>
  +	<LI><A HREF="obvious.html#Handling_the_server_timeout_case">Handling the server timeout cases and working with $SIG{ALRM}</A>
   	<LI><A HREF="obvious.html#Where_do_the_warnings_errors_go_">Where do the warnings/errors go?</A>
   	<LI><A HREF="obvious.html#Setting_environment_variables_fo">Setting environment variables for scripts called from CGI.</A>
   </UL>
  -<P><LI><A HREF="warnings.html"><B><FONT SIZE=+1>Warnings and Errors: Where and Why.</FONT></B></A></LI><P>
  +<P><LI><A HREF="warnings.html"><B><FONT SIZE=+1>Runtime Warnings and Errors: Where and Why.</FONT></B></A></LI><P>
   <UL>
   
   	<LI><A HREF="warnings.html#General_Advice">General Advice </A>
  @@ -343,6 +322,20 @@
   	<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 to eat up all the disk's space, when it goes wild.</A>
  +</UL>
   <P><LI><A HREF="security.html"><B><FONT SIZE=+1>Protecting Your Site</FONT></B></A></LI><P>
   <UL>
   
  @@ -369,18 +362,20 @@
   		<UL>
   
   			<LI><A HREF="databases.html#The_morning_bug">The morning bug</A>
  +			<LI><A HREF="databases.html#Opening_a_connection_with_differ">Opening a connection with different parameters</A>
   			<LI><A HREF="databases.html#Cannot_find_the_DBI_handler">Cannot find the DBI handler</A>
   			<LI><A HREF="databases.html#Apache_DBI_does_not_work">Apache:DBI does not work</A>
   		</UL>
   
  -		<LI><A HREF="databases.html#Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A>
  -		<UL>
  +	</UL>
   
  -			<LI><A HREF="databases.html#Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A>
  -			<LI><A HREF="databases.html#My_DB_module">My::DB module</A>
  -			<LI><A HREF="databases.html#My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A>
  -		</UL>
  +	<LI><A HREF="databases.html#mysql_use_result_vs_mysql_store">mysql_use_result vs. mysql_store_result.</A>
  +	<LI><A HREF="databases.html#Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A>
  +	<UL>
   
  +		<LI><A HREF="databases.html#Turning_the_SQL_queries_writing_">Turning the SQL queries writing into an short and simple task</A>
  +		<LI><A HREF="databases.html#My_DB_module">My::DB module</A>
  +		<LI><A HREF="databases.html#My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A>
   	</UL>
   
   </UL>
  @@ -399,20 +394,6 @@
   	<LI><A HREF="multiuser.html#ISPs_providing_mod_perl_services">ISPs providing mod_perl services - a fantasy or reality.</A>
   	<LI><A HREF="multiuser.html#Virtual_Hosts_in_the_guide">Virtual Hosts in the guide</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 to eat up all the disk's space, when it goes wild.</A>
  -</UL>
   <P><LI><A HREF="status.html"><B><FONT SIZE=+1>mod_perl Status. Peeking into the Server's Perl Innards</FONT></B></A></LI><P>
   <UL>
   
  @@ -428,11 +409,15 @@
   <P><LI><A HREF="debug.html"><B><FONT SIZE=+1>Debugging mod_perl</FONT></B></A></LI><P>
   <UL>
   
  -	<LI><A HREF="debug.html#Sometimes_script_works_Sometime">Sometimes script works, Sometimes Not</A>
  +	<LI><A HREF="debug.html#Sometimes_script_works_sometime">Sometimes script works, sometimes does not</A>
  +	<LI><A HREF="debug.html#Non_interactive_debugging_when_r">Non-interactive debugging when running under mod_perl</A>
   	<LI><A HREF="debug.html#Apache_DB_Run_the_interactive">Apache::DB - Run the interactive Perl debugger under mod_perl</A>
   	<LI><A HREF="debug.html#Debug_Tracing">Debug Tracing</A>
  -	<LI><A HREF="debug.html#Getting_some_decent_debug_info_w">Getting some decent debug info when running under mod_perl</A>
   	<LI><A HREF="debug.html#gdb_says_there_are_no_debugging_">gdb says there are no debugging symbols</A>
  +	<LI><A HREF="debug.html#Monitoring_error_log_file">Monitoring error_log file</A>
  +	<LI><A HREF="debug.html#Debugging_Signal_Handlers_SIG_">Debugging Signal Handlers ($SIG{FOO})</A>
  +	<LI><A HREF="debug.html#examples_of_strace_or_truss_us">examples of strace (or truss) usage</A>
  +	<LI><A HREF="debug.html#Devel_Peek">Devel::Peek</A>
   </UL>
   <P><LI><A HREF="browserbugs.html"><B><FONT SIZE=+1>Workarounds for some known bugs in browsers.</FONT></B></A></LI><P>
   <UL>
  @@ -447,6 +432,8 @@
   	<LI><A HREF="modules.html#Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A>
   	<LI><A HREF="modules.html#Apache_Request_libapreq_Gen">Apache::Request (libapreq) - Generic Apache Request Library</A>
   	<LI><A HREF="modules.html#Apache_PerlRun_Run_unaltered_">Apache::PerlRun - Run unaltered CGI scripts under mod_perl</A>
  +	<LI><A HREF="modules.html#Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A>
  +	<LI><A HREF="modules.html#Apache_PerlVINC_set_a_differe">Apache::PerlVINC - set a different @INC perl-location </A>
   </UL>
   <P><LI><A HREF="perl.html"><B><FONT SIZE=+1>Perl Reference</FONT></B></A></LI><P>
   <UL>
  @@ -472,6 +459,40 @@
   	<LI><A HREF="snippets.html#Accessing_variables_from_the_cal">Accessing variables from the caller's package</A>
   	<LI><A HREF="snippets.html#Handling_cookies">Handling cookies</A>
   </UL>
  +<P><LI><A HREF="hardware.html"><B><FONT SIZE=+1>Choosing an Operating System and Hardware</FONT></B></A></LI><P>
  +<UL>
  +
  +	<LI><A HREF="hardware.html#Is_it_important_">Is it important?</A>
  +	<LI><A HREF="hardware.html#Choosing_an_Operating_System">Choosing an Operating System</A>
  +	<UL>
  +
  +		<LI><A HREF="hardware.html#Stability_and_Robustness">Stability and Robustness</A>
  +		<LI><A HREF="hardware.html#Memory_Management">Memory Management</A>
  +		<LI><A HREF="hardware.html#Memory_Leakages">Memory Leakages</A>
  +		<LI><A HREF="hardware.html#Sharing_Memory">Sharing Memory</A>
  +		<LI><A HREF="hardware.html#Cost_and_Support">Cost and Support</A>
  +		<LI><A HREF="hardware.html#Discontinued_products">Discontinued products</A>
  +		<LI><A HREF="hardware.html#OS_Releases">OS Releases</A>
  +	</UL>
  +
  +	<LI><A HREF="hardware.html#Choosing_Hardware">Choosing Hardware</A>
  +	<UL>
  +
  +		<LI><A HREF="hardware.html#Site_traffic">Site traffic</A>
  +		<LI><A HREF="hardware.html#Cash">Cash</A>
  +		<LI><A HREF="hardware.html#Memory">Memory</A>
  +		<LI><A HREF="hardware.html#Internet_Connection">Internet Connection</A>
  +		<LI><A HREF="hardware.html#Bottlenecks">Bottlenecks</A>
  +		<LI><A HREF="hardware.html#Conclusion">Conclusion</A>
  +	</UL>
  +
  +</UL>
  +<P><LI><A HREF="advocacy.html"><B><FONT SIZE=+1>mod_perl Advocacy</FONT></B></A></LI><P>
  +<UL>
  +
  +	<LI><A HREF="advocacy.html#Thoughts_about_scalability">Thoughts about scalability</A>
  +	<LI><A HREF="advocacy.html#The_boss_and_the_developer">The boss and the developer</A>
  +</UL>
   <P><LI><A HREF="help.html"><B><FONT SIZE=+1>Getting Helped and Further Learning</FONT></B></A></LI><P>
   <UL>
   
  @@ -552,7 +573,7 @@
   <TR ALIGN=CENTER VALIGN=TOP>
   
   <TD ALIGN=CENTER VALIGN=CENTER><B><FONT SIZE=-1>Written by <A
  -HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 05/17/1999
  +HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 06/05/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.3       +42 -2     modperl-site/guide/install.html
  
  Index: install.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/install.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- install.html	1999/05/17 20:47:36	1.2
  +++ install.html	1999/06/05 17:47:19	1.3
  @@ -53,8 +53,11 @@
   	<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>
   	</UL>
   
  +	<LI><A HREF="#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -111,7 +114,7 @@
   
   <P>
   Here I will give only a short example of mod_perl installation. You should
  -read the real world scenarios for a more complete description.
  +read the <A HREF="././scenario.html#">Real World Scenarios Implementaion</A> for a more complete description.
   
   <P>
   As with any perl package, the installation of mod_perl is very easy and
  @@ -435,6 +438,43 @@
   <PRE>  make test
     make install
   </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.
  +
  +<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.
  +
  +<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!
  +
  +<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
  +better to build a fresh one to save you a mess.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</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>
  @@ -458,7 +498,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/15/1999
  +	     <BR>Last Modified at 06/05/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.4       +95 -1     modperl-site/guide/modules.html
  
  Index: modules.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/modules.html,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- modules.html	1999/05/08 17:46:32	1.3
  +++ modules.html	1999/06/05 17:47:20	1.4
  @@ -33,6 +33,8 @@
   	<LI><A HREF="#Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A>
   	<LI><A HREF="#Apache_Request_libapreq_Gen">Apache::Request (libapreq) - Generic Apache Request Library</A>
   	<LI><A HREF="#Apache_PerlRun_Run_unaltered_">Apache::PerlRun - Run unaltered CGI scripts under mod_perl</A>
  +	<LI><A HREF="#Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A>
  +	<LI><A HREF="#Apache_PerlVINC_set_a_differe">Apache::PerlVINC - set a different @INC perl-location </A>
   </UL>
   <!-- INDEX END -->
   
  @@ -184,6 +186,98 @@
   <P>
   See <A HREF="././porting.html#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>.
   
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<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.
  +
  +<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.
  +
  +<P>
  +For example to compress all html files on the fly, do:
  +
  +<P>
  +<PRE>  &lt;Files *.html&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::OutputChain Apache::GzipChain Apache::PassFile
  +  &lt;/Files&gt;
  +</PRE>
  +<P>
  +Remember that it will work only if the browsers 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.
  +
  +<P>
  +For example if you want to return compressed files which should pass in
  +addition through Embperl module, you would write:
  +
  +<P>
  +<PRE>  &lt;Location /test&gt;
  +    SetHandler &quot;perl-script&quot;
  +    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.
  +
  +<P>
  +See the module's documentaion for more details.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_PerlVINC_set_a_differe">Apache::PerlVINC - set a different @INC perl-location</A></H1></CENTER>
  +<P>
  +With that module, you can configure <CODE>@INC</CODE> and have modules reloaded for a given <CODE>Location</CODE>, e.g. say two versions of <CODE>Apache::Status</CODE>
  +are being hacked on in the same server, this fixup handler will simply
  +<CODE>delete $INC{ $filename }</CODE>, unshift the prefered <CODE>PerlINC</CODE> path into
  +<CODE>@INC</CODE>, and reload the file with <CODE>require()</CODE>:
  +
  +<P>
  +<PRE>  PerlModule Apache::PerlVINC
  +</PRE>
  +<P>
  +<PRE>  &lt;Location /dougm-status&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Status
  +  
  +    PerlINC /home/dougm/dev/modperl/lib
  +    PerlVersionINC On
  +    PerlFixupHandler Apache::PerlVINC
  +    PerlRequire Apache/Status.pm
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +<PRE>  &lt;Location /other-status&gt;
  +    SetHandler perl-script
  +    PerlHandler Apache::Status
  +  
  +    PerlINC /home/other/current/modperl/lib
  +    PerlVersionINC On
  +    PerlFixupHandler Apache::PerlVINC
  +    PerlRequire Apache/Status.pm
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +To address possible issues of namespace clashes during reload, the handler
  +could call $r-&gt;child_terminate() so the next server to load the
  +different versions will have a fresh namespace. (not a good idea in a high
  +load environment, of course.)
  +
  +<P>
  +If it is still absent from CPAN get it at: <A
  +HREF="http://perl.apache.org/~dougm/Apache-PerlVINC-0.01.tar.gz">http://perl.apache.org/~dougm/Apache-PerlVINC-0.01.tar.gz</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>
  @@ -207,7 +301,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/05/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.4       +2 -2      modperl-site/guide/multiuser.html
  
  Index: multiuser.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/multiuser.html,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- multiuser.html	1999/05/08 17:46:32	1.3
  +++ multiuser.html	1999/06/05 17:47:21	1.4
  @@ -25,7 +25,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>
   mod_perl for ISPs. mod_perl and Virtual Hosts.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="dbm.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="dbm.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="status.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  @@ -224,7 +224,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="dbm.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="control.html">Next</A>      ]
  +	     [    <A HREF="dbm.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="status.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  
  
  
  1.13      +60 -70    modperl-site/guide/obvious.html
  
  Index: obvious.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/obvious.html,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- obvious.html	1999/05/17 20:47:37	1.12
  +++ obvious.html	1999/06/05 17:47:21	1.13
  @@ -25,7 +25,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="hardware.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="performance.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,6 +36,7 @@
   		<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>
  @@ -50,7 +51,7 @@
   	<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</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>
  @@ -208,6 +209,15 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Additional_reading_references">Additional reading references</A></H2></CENTER>
  +<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>
  +.
  +
  +<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
  @@ -262,65 +272,65 @@
   <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> can add some (large?) overhead to server response times, and you certainly
  -wouldn't want Apache::StatINC module to be enabled in your production
  -site's configuration. But sometimes you want to have some Configuration
  -file (module) be reloaded without restarting the whole server. For this you
  -will have to add something like this in your code:
  +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>
  -Assume that you started your scripts with:
  +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(:subs);
  +  use Foo::Bar qw(:tags_group tag1 tag2);
   </PRE>
   <P>
  -Now to make a modification test and reload at runtime you have to use
  +Now to make a modification testing and reload at runtime you have to use
   something like this:
   
   <P>
  -<PRE>  # child's global variable to keep the timestamps 
  +<PRE>  # child's private global variable to keep the timestamps
     use vars qw(%MODIFIED);
  -  
  -  my $my_lib_root = &quot;/some/private/path&quot;;
  -  my $conf        = &quot;Foo/Bar.pm&quot;;
  -  my $conf_path   = &quot;$my_lib_root/$conf&quot;;
  -  
  -    # set modification time if it wasn't set before
  -    # Note: Use (stat $conf_path)[9] instead of -M test, if you reset
  -    # time with $^M=time
  -  $MODIFIED{$conf} ||= -M $conf_path;
  +    
  +  my $module = &quot;Foo::Bar&quot;;
     
  -    # now check whether it was changed (assuming the above wasn't
  -    # performed in this session
  -  if ($MODIFIED{$conf} != -M $conf_path){
  -      # only if deleted from %INC the require will be called below
  -    delete $INC{$conf};
  -  
  -        # this should be safe since @INC is being reset after we leave
  -        # the script, or you can skip this stage and require the script
  -        # with full path, remember that @INC now is different from the
  -        # one you have had when the script has been called at first time
  -    unshift @INC,$my_lib_root;
  -  
  -        # reread the file : use() wouldn't work here since it's compile time directive
  -    require Foo::Bar; 
  -  
  -        # now export the symbols (if you need them back :)
  -    import Foo::Bar qw(:subs);
  -  
  -        # Update the MODIFICATION times
  -    $MODIFIED{$conf} = -M $conf_path;
  +  (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 test this code in your
  -application. 
  +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.
  -(http://www.perl.com/CPAN-local/doc/FMTEYEWTK/use_vs_require)
  +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>
  @@ -658,7 +668,7 @@
   
   <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</A></H1></CENTER>
  +<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
  @@ -677,30 +687,10 @@
      
     die $@ if $@;
   </PRE>
  -<P>
  -But, as lately it was discovered <CODE>local $SIG{'ALRM'}</CODE> does not restore the original underlying C handler. Look at <CODE>Sys::Signal</CODE>
  -module, which should solve this problem.
  -
  -<P>
  -<CODE>Sys::Signal</CODE> - Set signal handlers with restoration of existing C sighandler
  -
  -<P>
  -Now use this code:
  -
  -<P>
  -<PRE>  use Sys::Signal ();
  -  eval {
  -    my $h = Sys::Signal-&gt;set(ALRM =&gt; sub { die &quot;timeout\n&quot; });
  -    alarm $timeout;
  -    ... do something thay may timeout ...
  -      alarm 0;
  -  };
  -  die $@ if $@;
  -</PRE>
   <P>
  -As of this writing it is still not entered CPAN and you can find it at <A
  -HREF="http://www.modperl.com/~dougm/perl/Sys-Signal-0.01.tar.gz">http://www.modperl.com/~dougm/perl/Sys-Signal-0.01.tar.gz</A>
  -. (But check the CPAN for the latest version anyway)
  +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>
  @@ -801,7 +791,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="hardware.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="warnings.html">Next</A>      ]
  +	     [    <A HREF="performance.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>
  @@ -814,7 +804,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/05/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.15      +34 -13    modperl-site/guide/performance.html
  
  Index: performance.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/performance.html,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- performance.html	1999/05/17 20:47:37	1.14
  +++ performance.html	1999/06/05 17:47:22	1.15
  @@ -25,7 +25,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>
   Performance. Benchmarks.</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="hardware.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <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>
   
  @@ -68,6 +68,7 @@
   	<LI><A HREF="#Using_1_under_mod_perl_and_be">Using $|=1 under mod_perl and better print() techniques.</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 -->
   
  @@ -1679,12 +1680,11 @@
   probably will want to optimize those, if your code is a way heavy.
   
   <P>
  -It is possible to profile code run under mod_perl with the Devel::DProf
  -module available on CPAN. However, you must have apache version 1.3b3 or
  -higher and the PerlChildExitHandler enabled. When the server is started,
  -Devel::DProf installs an END block to write the tmon.out file, which will
  -be run when the server is shutdown. Here is how to start and stop a server
  -with the profiler enabled:
  +It is possible to profile code run under mod_perl with the
  +<CODE>Devel::DProf</CODE> module available on CPAN. However, you must have apache version 1.3b3 or
  +higher and the PerlChildExitHandler enabled. When the server is started, <CODE>Devel::DProf</CODE> installs an END block to write the tmon.out file, which will be run when
  +the server is shutdown. Here is how to start and stop a server with the
  +profiler enabled:
   
   <P>
   <PRE>  % setenv PERL5OPT -d:DProf
  @@ -1695,12 +1695,25 @@
     % dprofpp
   </PRE>
   <P>
  -The Devel::DProf package is a Perl code profiler. This will collect
  -information on the execution time of a Perl script and of the subs in that
  -script. This information can be used to determine which subroutines are
  -using the most time and which subroutines are being called most often.
  +The <CODE>Devel::DProf</CODE> package is a Perl code profiler. This will collect information on the
  +execution time of a Perl script and of the subs in that script. This
  +information can be used to determine which subroutines are using the most
  +time and which subroutines are being called most often.
   
   <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>:
  +
  +<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.
  +
  +<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>
  @@ -1728,6 +1741,14 @@
   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="Sending_plain_HTML_as_a_compress">Sending plain HTML as a compressed output</A></H1></CENTER>
  +<P>
  +See <A HREF="././modules.html#Apache_GzipChain_compress_HTM">Apache::GzipChain - compress HTML (or anything) in the OutputChain</A>
  +
  +
  +
   <P><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>
  @@ -1738,7 +1759,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="porting.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="hardware.html">Next</A>      ]
  +	     [    <A HREF="porting.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>
  @@ -1751,7 +1772,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/05/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.5       +12 -5     modperl-site/guide/perl.html
  
  Index: perl.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/perl.html,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- perl.html	1999/05/08 17:46:33	1.4
  +++ perl.html	1999/06/05 17:47:23	1.5
  @@ -105,7 +105,8 @@
     ----------------
     use vars qw($q);
     use CGI;
  -  use My::HTML qw($q);
  +  use lib qw(.); 
  +  use My::HTML qw($q); # My/HTML.pm in the same dir as script.pl
     $q = new CGI;
     
     My::HTML::printmyheader();
  @@ -136,6 +137,7 @@
       # Whatever you want to do with $q... e.g.
       print $q-&gt;header();
     }
  +  1;
     -------------------
   </PRE>
   <P>
  @@ -169,8 +171,9 @@
     ----------------
     use vars qw($q);
     use CGI;
  -  use My::HTML qw($q);
  -  use My::Doc  qw($q);
  +  use lib qw(.); 
  +  use My::HTML qw($q); # My/HTML.pm in the same dir as script.pl
  +  use My::Doc  qw($q); # Ditto
     $q = new CGI;
     
     My::HTML::printmyheader();
  @@ -200,6 +203,7 @@
     
       My::Doc::printtitle('Guide');
     }
  +  1;
     -------------------
   </PRE>
   <P>
  @@ -224,6 +228,7 @@
       
       print $q-&gt;h1($title);
     }
  +  1;
     -------------------
   </PRE>
   <P>
  @@ -257,6 +262,7 @@
                      bar =&gt; 'BARRR',
                     },
     );
  +  1;
   </PRE>
   <P>
   Now in packages that want to use the configuration variables I have either
  @@ -268,8 +274,9 @@
   <P>
   <PRE>  package My::HTML;
     use strict;
  +  use lib qw(.);
       # Global Configuration now aliased to global %c
  -  use My::Config ();
  +  use My::Config (); # My/Config.pm in the same dir as script.pl
     use vars qw(%c);
     *c = \%My::Config::c;
     
  @@ -318,7 +325,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/05/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.16      +10 -12    modperl-site/guide/porting.html
  
  Index: porting.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/porting.html,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- porting.html	1999/05/17 20:47:37	1.15
  +++ porting.html	1999/06/05 17:47:23	1.16
  @@ -64,7 +64,7 @@
   	<LI><A HREF="#Filehandlers_and_locks_leakages">Filehandlers and locks leakages</A>
   	<UL>
   
  -		<LI><A HREF="#Sometimes_it_Works_Sometimes_Not">Sometimes it Works Sometimes Not (Very important!)</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>
   	</UL>
  @@ -611,17 +611,18 @@
   <PRE>  PerlTaintCheck On
   </PRE>
   <P>
  -Now, any and all code compiled inside httpd will be taint checked. 
  +Now, any and all code compiled inside httpd will be taint checked.
   
   <P>
   The environment variable PERL5OPT can be used to set additional perl
  -startup flags such as -d and -D. See perlrun.
  +startup flags such as -d and -D. See
  +<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>
   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> isn't <CODE>On</CODE>.
  +<CODE>PerlTaintCheck</CODE> is not <CODE>On</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -1061,7 +1062,7 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Sometimes_it_Works_Sometimes_Not">Sometimes it Works Sometimes Not (Very important!)</A></H2></CENTER>
  +<CENTER><H2><A NAME="Sometimes_it_Works_Sometimes_it_">Sometimes it Works Sometimes it does Not (Very important!)</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
  @@ -1169,7 +1170,7 @@
     &lt;/Location&gt;
   </PRE>
   <P>
  -See <A HREF="#">Apache::PerlRun - a closer look</A>
  +See <A HREF="#Apache_PerlRun_a_closer_look">Apache::PerlRun - a closer look</A>
   
   
   
  @@ -1296,7 +1297,7 @@
       $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 error to be emailed to us, ofcourse -
  +    # 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) {
     
  @@ -1345,11 +1346,8 @@
     &lt;B&gt;Oops, An error has happened.&lt;/B&gt;&lt;P&gt;
       |;  
     
  -    print HTML::warn_box($message);
  +    print $message;
     
  -      # print the tail!
  -    HTML::custom_tail();
  -  
         # send email report if appropriate
       if ($should_email){
     
  @@ -1560,7 +1558,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/15/1999
  +	     <BR>Last Modified at 06/05/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.14      +29 -11    modperl-site/guide/scenario.html
  
  Index: scenario.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/scenario.html,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- scenario.html	1999/05/17 20:47:38	1.13
  +++ scenario.html	1999/06/05 17:47:24	1.14
  @@ -302,10 +302,6 @@
   so we have to compile with the same compiler!!!
   
   <P>
  -Notice that <STRONG>ALL</STRONG>  <CODE>APACI_ARGS</CODE> (below) must be passed as one long line!!! I have wrapped them to allow
  -easier reading.
  -
  -<P>
   <PRE>  % cd /usr/src/httpd_perl/mod_perl-1.19
   </PRE>
   <P>
  @@ -317,14 +313,19 @@
     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,
  +  APACI_ARGS=--sbindir=/usr/local/sbin/httpd_perl, \
  +         --sysconfdir=/usr/local/etc/httpd_perl, \
  +         --localstatedir=/usr/local/var/httpd_perl, \
  +         --runtimedir=/usr/local/var/httpd_perl/run, \
  +         --logfiledir=/usr/local/var/httpd_perl/logs, \
            --proxycachedir=/usr/local/var/httpd_perl/proxy
   </PRE>
   <P>
  +Notice that <STRONG>ALL</STRONG>  <CODE>APACI_ARGS</CODE> (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.
  +
  +<P>
   As with <CODE>httpd_docs</CODE> you might need other modules like
   <CODE>mod_rewrite</CODE>, so add them here:
   
  @@ -964,6 +965,23 @@
   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.
  +
  +<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)
  +
  +<P>
  +Apache does caching as well. It's relevant to mod_perl only if you produce
  +proper headers so your scripts' output can be cached. See apache
  +documentation for more details on configuration of this capability.
  +
  +<P>
   Ask Bjoern Hansen has written a <CODE>mod_proxy_add_forward.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>
  @@ -985,7 +1003,7 @@
   should be able to access REMOTE_ADDR as usual.
   
   <P>
  -IF you are using Apache::{Registry,PerlRun} - do it like this:
  +If you are using <CODE>Apache::{Registry,PerlRun}</CODE> - do it like this:
   
   <P>
   in startup.pl:
  @@ -1087,7 +1105,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#This_document_s_Author">Stas Bekman</A>.
  -	     <BR>Last Modified at 05/15/1999
  +	     <BR>Last Modified at 06/05/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.2       +2 -2      modperl-site/guide/security.html
  
  Index: security.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/security.html,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- security.html	1999/05/17 20:47:38	1.1
  +++ security.html	1999/06/05 17:47:24	1.2
  @@ -25,7 +25,7 @@
   <A HREF="http://perl.apache.org"><IMG SRC="images/mod_perl.gif" ALT="Mod Perl Icon" BORDER=0 HEIGHT=30 WIDTH=90 ALIGN=RIGHT></A>
   Protecting Your Site</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="control.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>
   
  @@ -230,7 +230,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="warnings.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="databases.html">Next</A>      ]
  +	     [    <A HREF="control.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>
  
  
  
  1.13      +2 -2      modperl-site/guide/snippets.html
  
  Index: snippets.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/snippets.html,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- snippets.html	1999/05/17 20:47:38	1.12
  +++ snippets.html	1999/06/05 17:47:25	1.13
  @@ -25,7 +25,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>
   Code Snippets</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="perl.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="help.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="perl.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="hardware.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  @@ -259,7 +259,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="perl.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="help.html">Next</A>      ]
  +	     [    <A HREF="perl.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="hardware.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  
  
  
  1.13      +2 -2      modperl-site/guide/status.html
  
  Index: status.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/status.html,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- status.html	1999/05/08 17:46:33	1.12
  +++ status.html	1999/06/05 17:47:25	1.13
  @@ -25,7 +25,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>
   mod_perl Status. Peeking into the Server's Perl Innards</H1>
   <HR WIDTH="100%">
  -	    [    <A HREF="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="debug.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <A HREF="multiuser.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="debug.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
   <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
   <UL>
   
  @@ -153,7 +153,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="control.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="debug.html">Next</A>      ]
  +	     [    <A HREF="multiuser.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="debug.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  
  
  
  1.3       +232 -204  modperl-site/guide/strategy.html
  
  Index: strategy.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/strategy.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- strategy.html	1999/05/17 20:47:38	1.2
  +++ strategy.html	1999/06/05 17:47:26	1.3
  @@ -1,7 +1,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Picking the Right Strategy</TITLE>
  +   <TITLE>mod_perl guide: Choosing the Right Strategy</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -23,16 +23,16 @@
   <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>
  -Picking the Right Strategy</H1>
  +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 -->
   <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_Deploying_Schemas_Overv">mod_perl Deploying Schemas Overview</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_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>
  @@ -56,27 +56,27 @@
   <P>
   <CENTER><H1><A NAME="Do_it_like_me_">Do it like me?!</A></H1></CENTER>
   <P>
  -There is no such a thing as a <STRONG>RIGHT</STRONG> strategy in web server business, though there are the wrong ones. Never
  -believe a person, saying: <EM>"Do it this way, this is the best!"</EM>. As the old saying says: <EM>"Trust but verify"</EM>. There are too many technologies out there to pick from, and it might take
  -an enormous investment of time and money to try to validate each one,
  -before deciding what is your favorite one. Keeping this idea in mind, I
  -will try to present different combinations of mod_perl and other
  -technologies or just standalone mod_perl. How these things work together,
  -what are the good and what are the bad properties of each one, how hard to
  -install and maintain them, what approaches should be used and what to be
  -avoided.
  +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.
   
   <P>
  -To make myself clear, I would not talk about any technologies and tools,
  -but the ones complementing mod_perl.
  +To be clear, I will not address all technologies and tools, but limit this
  +discussion to those complementing mod_perl.
   
   <P>
  -Please let me stress it again: <STRONG>DO NOT</STRONG> blindly copy someone's setup and hope for a good. Choose what is best for
  -your situation. it might take _some_ effort to find it out.
  +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.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="mod_perl_Deploying_Schemas_Overv">mod_perl Deploying Schemas Overview</A></H1></CENTER>
  +<CENTER><H1><A NAME="mod_perl_Deployment_Overview">mod_perl Deployment Overview</A></H1></CENTER>
   <P>
   There are several different ways to build, configure and deploy your
   mod_perl enabled server. Some of them are:
  @@ -84,70 +84,73 @@
   <OL>
   <P><LI>
   <P>
  -Having 1 binary and 1 config file (one big binary for mod_perl)
  +Having one binary and one config file (one big binary for mod_perl).
   
   <P><LI>
   <P>
  -Having 2 binaries and 2 config files (one big binary for mod_perl and one
  -small for static object like images)
  +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 1 DSO style binary, mod_perl loadable object and 2 config files
  +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 week
  -documentation and is still subject to change and is rather more complex)
  +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 proxy server in the http accelerator mode.
  +Any of the above plus a reverse proxy server in http accelerator mode.
   
   </OL>
   <P>
  -If you are a newbie, I would recommend you to start with the first option
  -and work on getting your feet wet with apache and mod_perl, then decide
  -whether to move to the second one which allows a better tuning for the
  -price of more complicated administration or to the more
  -state-of-the-art-yet-suspiciously-new DSO system (third one) or/and to the
  -forth option which brings you even more power.
  +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.
   
   <P>
  -First option will kill your production site if you serve a lot of static
  -data with a 2-12 MB webservers. On the other hand while testing you will
  -have no other server interaction to mask or add to your errors.
  +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>
  -Second option allows you to seriously tune the two servers and get the
  -maximum performance. On the other hand you have to deal with proxying or
  -fancy site design to keep the two servers in step. Choose serving on
  -multiple ports, multiple IPs, etc... You also have to admimistrate one more
  -server.
  +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.
   
   <P>
  -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 even
  -shared amongst multiple servers. Again, it is bleeding edge and still sort
  -of platform wonky, but your milegue may vary. See <A HREF="././scenario.html#mod_perl_server_as_DSO">mod_perl server as DSO</A>.
  +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>.
   
   <P>
  -Forth option (proxy in http accelerator mode) - improves the performance by
  -caching and buffering, once correctly configured and tuned.
  +The fourth option (proxy in http accelerator mode), once correctly
  +configured and tuned, improves performance by caching and buffering page
  +results.
   
   <P>
  -The rest of this chapter discuss the pros and the cons of each of the
  -presented schemas. <A HREF="././scenario.html#">Real World Scenarios Implementaion</A>
  -describes the implementation techniques of described schemas.
  +The rest of this chapter discusses the pros and the cons of each of these
  +presented configurations.
  +<A HREF="././scenario.html#">Real World Scenarios Implementaion</A>
  +describes the implementation techniques of these schemas.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><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 to it the 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.
  +take your plain apache server and add mod_perl, like you add any other
  +apache module. You continue to run it at the port it was running before.
  +You probably want to try this before you proceed to more sophisticated and
  +complex techniques.
   
   <P>
   The Advantages:
  @@ -155,16 +158,18 @@
   <UL>
   <P><LI>
   <P>
  -Simplicity of installation. You just follow the installation instructions,
  -configure it, restart the server and you have finished.
  +Simplicity. You just follow the installation instructions, configure it,
  +restart the server and you are done.
   
   <P><LI>
   <P>
  -You do not have to think about using additional ports as we will see later.
  +No network changes. You do not have to worry about using additional ports
  +as we will see later.
   
  +<P><LI>
   <P>
  -You get a very fast server, you see an enormous speedup from the first
  -moment you have started to use it.
  +Speed. You get a very fast server, you see an enormous speedup from the
  +first moment you start to use it.
   
   </UL>
   <P>
  @@ -173,43 +178,48 @@
   <UL>
   <P><LI>
   <P>
  -A mod_perl process' size is huge compared to the plain apache you have got
  -used to (starting from 4Mb at the startup and growing to 10Mb and more,
  -depending on what and how do you use it). You probably have a few tens of
  -children processes. The memory adds up. Your memory demands are growing in
  -an order of magnitude. But this is something you will have to live with, if
  -you are in the mod_perl boat. Memory is cheap nowadays and the performance
  -boost mod_perl gives to your services worths every 100Mb of RAM you add.
  -
  -<P>
  -While you are calm to have these monsters to serve you scripts with the
  -monsters' speed, you should be very worried about them serving your static
  -objects, like images and html files. It means that if you will need more
  -processes to serve these - more memory, 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 a static object request
  -(or only one request if you have the
  -<CODE>KeepAlive</CODE> directive turned <CODE>ON</CODE>). 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.
  +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
  +
  +<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.
  +
  +<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.
   
   <P><LI>
   <P>
  -Another drawback that you cannot afford is having the huge process to wait
  -till the client with slow connection will receive the whole response. While
  -it might take a few milliseconds for your script to complete the request,
  -there is a chance it will be still busy for another 5 seconds or even
  -minutes if the request has come from the slow connection client. As in the
  -previous drawback, proxy comes to solve this problem. More on proxies
  -later.
  +Another drawback of this approach is that when serving output to a client
  +with a slow connection, the huge mod_perl-enabled server process (with all
  +of its system resources) will be tied up until the response is completely
  +written to the client. While it might take a few milliseconds for your
  +script to complete the request, there is a chance it will be still busy for
  +some number of seconds or even minutes if the request is from a slow
  +connection client. As in the previous drawback, a proxy solution can solve
  +this problem. More on proxies later.
   
   <P>
   Proxying dynamic content is not going to help much if all the clients are
  -on a fast local net. For example if you are an administrator of the
  -Intranet. On opposite, it can make things worse. But still remember that
  -some of your Intranet users might work from home through the slow modem
  -links.
  +on a fast local net (for example, if you are administering an Intranet.) On
  +the contrary, it can decrease performance. Still, remember that some of
  +your Intranet users might work from home through the slow modem links.
   
   </UL>
   <P>
  @@ -217,8 +227,8 @@
   started.
   
   <P>
  -Of course if your site is serving only the mod_perl scripts, this might be
  -the most perfect choice for you!
  +And of course, if your site is serving only mod_perl scripts, this might be
  +the perfect choice for you!
   
   <P>
   For implementation notes see :
  @@ -228,22 +238,22 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="One_Plain_and_One_mod_perl_enabl">One Plain and One mod_perl enabled Apache Servers</A></H1></CENTER>
  +<CENTER><H1><A NAME="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 your scripts under mod_perl, you
  -will notice that the httpd processes consume a huge amount of memory, from
  -5M to 25M and more. That is the price you pay for the enormous speed
  +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.
   
   <P>
  -It is an overkill to serve static objects like images and html documents
  -with these large processes. The best 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 take care of requests to dynamic (generated)
  +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>
  -Since now on, I will refer to these two servers as <STRONG>httpd_docs</STRONG>
  +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>
  @@ -252,23 +262,28 @@
   <UL>
   <P><LI>
   <P>
  -Heavy mod_perl processes serving only dynamic requests. So we need much
  -less servers - memory requirements are drastically going down. While this
  -is always correct for static HTML object, you might still have a problem
  -with static object requests from the generated HTML. You must use a fully
  -qualified URL and not a relative one! When you generate an HTML which has
  -relative references to images or other static object - client's browser
  -sets its base url to point to
  -<CODE>httpd_perl</CODE> server's. And all the image requests will go to the heavy <CODE>httpd_perl</CODE>. Be aware! You solve this by either using a full URLs to the <CODE>httpd_docs</CODE> server (the fastest) or rewriting the requests back to <CODE>httpd_docs</CODE> (much 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>)
  +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>
   <P>
  -<CODE>MaxClients</CODE>, <CODE>MaxRequestsPerChild</CODE> and related parameters now can 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.
  +<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.
   
   <P>
  -Now we can spawn many light weighted <CODE>httpd_docs</CODE> servers and just a few heavy <CODE>httpd_perl</CODE> servers.
  +Now we can run many lightweight <CODE>httpd_docs</CODE> servers and just a few heavy <CODE>httpd_perl</CODE> servers.
   
   </UL>
   <P>
  @@ -282,34 +297,35 @@
   <UL>
   <P><LI>
   <P>
  -A need for 2 different configuration files, 2 log files sets and etc. We
  -need a special directories layout to manage these. While some directories
  -can be shared between the two servers, like <CODE>include</CODE>
  -directory, storing the apache include files (assuming that both are built
  -from the same source distribution), most of them should be separated and
  -configuration files updated to reflect the changes.
  +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.)
   
   <P><LI>
   <P>
  -A need for 2 sets of controlling scripts (startup/shutdown)
  +A need for two sets of controlling scripts (startup/shutdown)
   
   <P><LI>
   <P>
  -If you are processing log files, now you probably will have to merge the 2
  -separate log files.
  +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>
  -We still have the problem of mod_perl process spending its precious time to
  -server slow clients, when the request was processed long time ago, exactly
  -like in 1 server approach. Proxy solves this, and will be covered in the
  -next sections.
  +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>
  -Exactly as with only one server approach, this is not a disadvantage if you
  -are on the fast local Intranet. Most chances that you do not want a
  -buffering server on your way.
  +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>
  @@ -322,9 +338,9 @@
   <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 functionality needed from the the light server is static
  -objects serving, you can get away with non-apache servers, whose memory
  -footprint is even smaller. <CODE>thttpd</CODE> has been reported to be about 5 times faster then apache (especially under
  +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.
   
  @@ -342,7 +358,7 @@
   
   <P><LI>
   <P>
  -More memory saving. Apache is about 4 times bigger then <STRONG>thttpd</STRONG>, it if you spawn 30 children you use about 30M of memory, while <STRONG>thttpd</STRONG>
  +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.
   
  @@ -358,8 +374,8 @@
   <UL>
   <P><LI>
   <P>
  -Lucks some apache's features, like access control, error redirection,
  -logfile format and so on. 
  +Lacks some of apache's features, like access control, error redirection,
  +customizable logfile formats, and so on. 
   
   </UL>
   <P>
  @@ -382,7 +398,7 @@
   
   <P>
   Now I am going to convince you that you _want_ to use a proxy server (in
  -the http accelerator mode). The reasons are:
  +the http accelerator mode). The advantages are:
   
   <UL>
   <P><LI>
  @@ -390,96 +406,98 @@
   Allow serving of static objects from the proxy's cache (objects that
   previously were entirely served by the httpd_docs server). 
   
  +<P><LI>
   <P>
  -You get less I/O activity to read the object 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. (I/O
  -+1 points, faster static object serving +1 point)
  +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.
   
   <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 getting
  +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>
   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 a speed of
  -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 pretty average script that
  -generates this output in 0.5 secs. How much time the server will wait
  -before user will get the whole output down his way? A simple calculation
  -reveals pretty scaring numbers - it will have to wait for another 6 secs
  -(20kb/3.6kb), when it could serve another 12 (6/0.5) requests at the time
  -it was stalled. This very simple example shows us that we need 12 times
  -less children running, which means you will need 12 fold times less 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>
  -To make your numbers of download time 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 I was
  -talking about before, many times 5-10 times smaller.
  +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>
  +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.
   
  -<P>
  -(+3 point for memory cut up, I give it 3 times more points for the savings
  -we get with this most important functionality)
  -
   <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 serves as a front end,
  +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
  +other servers. (Of course this is pretty big topic, and it would not be
   included in the scope of this document)
   
  +<P><LI>
   <P>
  -(+1 point for flexibility to change things at the background and making
  -user to bookmark only one URL)
  +For security reasons, using any httpd accelerator (or a proxy in httpd
  +accelerator mode) is essential because you do not let your internal server
  +get directly attacked by arbitrary packets from whomever. The httpd
  +accelerator and internal server communicate in expected HTTP requests. This
  +allows for only your public ``bastion'' accelerating www server to get
  +hosed in a successful attack, while leaving your internal data safe.
   
  +</UL>
  +<P>
  +The disadvantages are:
  +
  +<UL>
   <P><LI>
   <P>
   Of course there are drawbacks. Luckily, these are not functionality
  -drawbacks, but more of administration hassle. Yes, you add another program
  -to worry about, 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. May be a watchdog script running at the
  +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.
   
  +<P><LI>
   <P>
  -Proxy servers can be configured to be light or heavy, admin must decide
  -what gives the highest performance for his application. Proxy server like
  +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 serving.
  -
  -<P>
  -(-1 point for administration overhead, very small but overhead. -1 point
  -for memory consuming)
  +for faster service.
   
   </UL>
   <P>
  -So let's sum up the points. We have 4 (6-2) points for the proxy server and
  -I believe I have succeeded to convince you, that you want it :)
  +Have I succeeded in convincing you that you want the proxy server?
   
   <P>
  -If you are on the local network, then the big benefit of 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.
  +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.
   
   <P>
  -As of this writing 2 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 2 of them.
  +As of this writing the two proxy implementations are known to be used in
  +bundle with mod_perl - <STRONG>squid</STRONG> proxy server and <STRONG>mod_proxy</STRONG> which is a part of the apache server. Let's compare the two of them.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -490,17 +508,17 @@
   <UL>
   <P><LI>
   <P>
  -Caching of static objects. So these are being served much faster taking
  +Caching of static objects. So these are being served much faster assuming
   that your cache size is big enough to keep the most requested objects in
   the cache.
   
   <P><LI>
   <P>
  -Buffering of dynamic content, by taking the burden of returning the
  -generated by mod_perl server content to the slow clients, thus freeing
  -mod_perl servers from wasteful waiting for the slow clients to download the
  -data. Freed servers immediately switch to serve other requests, thus your
  -number of required servers goes drastically down.
  +Buffering of dynamic content, by taking the burden of returning the content
  +generated by mod_perl servers to slow clients, thus freeing mod_perl
  +servers from waiting for the slow clients to download the data. Freed
  +servers immediately switch to serve other requests, thus your number of
  +required servers goes dramatically down.
   
   <P><LI>
   <P>
  @@ -548,10 +566,10 @@
   </UL>
   <P>
   The presented pros and cons lead to an idea, that probably you might want
  -squid more for its dynamic content buffering features, 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.
  +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>
   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
  @@ -571,7 +589,7 @@
   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 to fix redirects in a way that keeps the client's view of both
  +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
  @@ -590,7 +608,7 @@
   
   <P><LI>
   <P>
  -<CODE>ProxyPass</CODE> and <CODE>ProxyPassReverse</CODE> directives allows you to hide the internal redirects, so if <CODE>http://nowhere.com/modperl/</CODE> is actually
  +<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>
  @@ -599,14 +617,13 @@
   </PRE>
   <P><LI>
   <P>
  -It does mod_perl output buffering as squid. See the implementation notes
  -for more details
  +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><LI>
   <P>
   It even does caching. You have to produce correct <CODE>Content-Length</CODE>,
  -<CODE>Last-Modified</CODE> and <CODE>Expires</CODE> http headres for it to work. If some dynamic content is not to change
  -constantly, you can dramatically increase performance with caching it by
  +<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>
  @@ -614,6 +631,17 @@
   <CODE>ProxyPass</CODE> happens before the authentication phase, so you do not have to worry about
   authenticating twice.
   
  +<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>
  +The latest (from apache 1.3.6) Apache proxy accel mode reported to be very
  +stable.
  +
   </UL>
   <P>
   The Disadvantages:
  @@ -647,7 +675,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/04/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.14      +10 -7     modperl-site/guide/warnings.html
  
  Index: warnings.html
  ===================================================================
  RCS file: /export/home/cvs/modperl-site/guide/warnings.html,v
  retrieving revision 1.13
  retrieving revision 1.14
  diff -u -r1.13 -r1.14
  --- warnings.html	1999/05/17 20:47:39	1.13
  +++ warnings.html	1999/06/05 17:47:26	1.14
  @@ -1,7 +1,7 @@
   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
   <HTML>
   <HEAD>
  -   <TITLE>mod_perl guide: Warnings and Errors: Where and Why.</TITLE>
  +   <TITLE>mod_perl guide: Runtime Warnings and Errors: Where and Why.</TITLE>
      <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
      <META NAME="Author" CONTENT="Bekman Stas">
      <META NAME="Description" CONTENT="All Apache/Perl related information: Hints, 
  @@ -23,9 +23,9 @@
   <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>
  -Warnings and Errors: Where and Why.</H1>
  +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="security.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  +	    [    <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>
   
  @@ -98,6 +98,9 @@
   see the rwrite messages if LogLevel is set to debug.
   
   <P>
  +This bug has been fixed in mod_perl 1.19_01 (CVS version).
  +
  +<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>
   <P>
  @@ -196,10 +199,10 @@
   
   <P>
   <PRE> Looks like you have a $SIG{__DIE__} handler installed (Carp::confess?).
  - That's what's expected if so
  + That's what's expected if so.
   </PRE>
   <P>
  -It wasn't in my case, but may be yours 
  +It wasn't in my case, but may be yours. 
   
   <P>
   Bryan Miller said:
  @@ -417,7 +420,7 @@
   	     Amazon.com</a>.
   
   	     <HR>
  -	     [    <A HREF="obvious.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="control.html">Next</A>      ]
   
   <CENTER><TABLE CELLSPACING=2 CELLPADDING=2 WIDTH="100%" >
   <TR ALIGN=CENTER VALIGN=TOP>
  @@ -430,7 +433,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/04/1999
         </FONT>
       </B>
     </TD>
  
  
  
  1.1                  modperl-site/guide/advocacy.html
  
  Index: advocacy.html
  ===================================================================
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
  <HTML>
  <HEAD>
     <TITLE>mod_perl guide: mod_perl Advocacy</TITLE>
     <META NAME="GENERATOR" CONTENT="Mozilla/3.04Gold (X11; I; AIX 4.1) [Netscape]">
     <META NAME="Author" CONTENT="Bekman Stas">
     <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>
  mod_perl Advocacy</H1>
  <HR WIDTH="100%">
  	    [    <A HREF="hardware.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="help.html">Next</A>      ]<HR><!-- INDEX BEGIN -->
  <P><B><FONT SIZE=-1>Table of Contents:</FONT></B></P>
  <UL>
  
  	<LI><A HREF="#Thoughts_about_scalability">Thoughts about scalability</A>
  	<LI><A HREF="#The_boss_and_the_developer">The boss and the developer</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="Thoughts_about_scalability">Thoughts about scalability</A></H1></CENTER>
  <P>
  It depends on what you ought to do on the web. If all you want is a simple
  guest book or very simple DB gateway you can get away with any of
  EASY_AND_FAST_TO_DEVELOP_TOOLS (Exchange, MS IIS, Lotus Notes, etc). The
  problem is that as my experience shows, in short terms you will want more
  functionality, so you start looking for really creative ways to get this
  functionalily from these _easy_ tools, and when you make it if at all, your
  boss asks for even more functionality and then you understand that you have
  got no scalability and you have to port all your code to mod_perl or
  another powerful equivalent. Then you look back and see how much time and
  money was wasted with that EASY_AND_FAST_TO_DEVELOP_TOOLS.
  
  <P>
  The point is that if you are serious about Internet and script driven
  sites, sooner or later you will need a lot of flexibility and functionality
  from your script/code base. So you better choose a development platform
  with power of doing things your way at first place. While you might spend a
  little more time and money to learn the language and its concepts, and to
  code the basic skeleton, later code extension and modifications would be a
  snap.
  
  <P>
  <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  <CENTER><H1><A NAME="The_boss_and_the_developer">The boss and the developer</A></H1></CENTER>
  <P>
  While there is a known factor of boss character in the life of developer,
  the developer should make an investigation work before he goes to ask for
  an approval to go with mod_perl. Personally, when I discovered mod_perl I
  did a lot of testing and coding at home and at work. Once I have had a
  working heavy application, I came to my boss with 2 URLs - one for the
  plain CGI server and the other for mod_perl enabled server. It took about
  30 secs for my boss to say: ``Go with it''. Of course the moment I did it,
  I have had to provide all the support for other developers, that is why I
  took my time to learn it in first place (that is how this guide was born!).
  
  <P>
  Most chances that you are doomed to failure if you are showing some very
  fast working site, and persuade your boss to give it a try but the moment
  you start to code/port the scripts your are getting stuck cause you are
  unfamiliar with mod_perl pecularities. If your boss follows your
  development process closely and sees you not making any progress, he might
  say - forget it, we fall back to old foo platform. And if this happens, you
  made the mistake twice - you are not developing under mod_perl and chances
  that your boss will give you and mod_perl a second chances are very little.
  
  <P>
  I am not here to discourage you to advocate mod_perl at your working place.
  I am here to warn you that if you want to advocate something, you cannot
  start doing this based on the naked facts. You have to learn the technology
  in subject in first place, get acquanted with the ways you can get helped
  in case of trouble. The ideal scenario would be to show your boss a heavy
  CGI which is running much faster under mod_perl, and when she gets
  impressed, ask for an evaluation time (I know that the chances you get it
  are not very high, that is why I called it ideal), argument the need for
  evaluation and studying time with an enormous time save-up in the future.
  When this time is out make sure you can provide the support for mod_perl or
  at least to be a connecting bridge between your organization and the
  mod_perl community.
  
  <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="hardware.html">Prev</A> |      <A HREF="index.html">Main Page</A> | <A HREF="help.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/05/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>
  	    
  
  

Mime
View raw message