perl-modperl-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sbek...@locus.apache.org
Subject cvs commit: modperl-site/guide/code DB_File-Lock2.pm My-DB.pm mysql-3.22.29_backup.pl mysql-3.22.29_restore.pl mysql-3.22.30+_backup.pl mysql-3.22.30+_restore.pl
Date Sat, 04 Mar 2000 20:31:54 GMT
sbekman     00/03/04 12:31:53

  Modified:    guide    CHANGES config.html control.html
                        correct_headers.html databases.html dbm.html
                        debug.html download.html help.html index.html
                        install.html intro.html mod_perl_guide.pdf.gz
                        modules.html performance.html porting.html
                        scenario.html snippets.html strategy.html
  Added:       guide/code DB_File-Lock2.pm My-DB.pm mysql-3.22.29_backup.pl
                        mysql-3.22.29_restore.pl mysql-3.22.30+_backup.pl
                        mysql-3.22.30+_restore.pl
  Log:
  * help: updated the mod_perl list subscription info, added the
    advocacy list info.
  
  * download: HA section - added more links (Robin Berjon, Gerd Knops)
  
  * strategy: added a new section "When One Machine is not Enough for
    SQL DB and mod_perl" (Vivek Khera, Jeffrey W. Baker, John Armstrong,
    Mike Miller, Leslie Mikesell, Tom Brown, Ed Phillips, Marko van der
    Puil) Special thanks to Jeffrey for working on the this section
    before it went into the Gude.
  
  * perfomance: added the section "Memory Swapping is Considered Bad"
  
  * modules: added the Apache::GTopLimit and Apache::Watchdog::RunAway
    modules description
  
  * performance: new section "Is my Code Shared"
  
  * download: added links to DB sites and "Low-Cost Unix Database
    Differences" comparison page.
  
  * config: new section "Enabling Remote Server Configuration Reports"
  
  * performance: new section "Calculating Real Memory Usage"
  
  * scenario: mod_proxy section has been rewritten and extended with
    lots of OS specific information (Joshua Chamas, Oleg Bartunov,
    Gerald Richter, Radu Greab, Peter Haworth, Vivek Khera)
  
  * performance: rewritten "Object Methods Calls Versus Function Calls"
    and splitted into the original section and "Imported Symbols and
    Memory Usage" (James G Smith, David Mitchell, Doug, Matt Sergeant,
    Bill Moseley, Autarch)
  
  * performance: added "Reducing the Number of stat() Calls" (Steve
    Reppucci)
  
  * install: added a note of how to force CPAN shell to install mod_perl
    when the same version is already installed.
  
  * scenario: added "mod_rewrite Examples" (Vivek Khera, Tom Mornini)
  
  * databases: added "Optimize: Run Two SQL Engine Servers" (Pascal
    Eeftinck)
  
  * snippets: added "Using DESTROY to Finalize Output" with solutions to
    redirection loghandler fixes (Michael Blakeley)
  
  * scenario: added to the section "One Plain and One mod_perl enabled
    Apache Servers" --target option to make the ./configure stage
    somewhat simpler. (James Furness)
  
  * snippets: added 2 modified versions of the mysql backup/restore
    scripts to work with 3.22.30+ (Ward Vandewege)
  
  * Moved complete files, previously enlisted in the text, to the
    external files. This makes the browsing faster when the files are
    very big.  Added new POD tag =code to create the link to the
    external file at the pod2html conversion stage
  
  * review: Ged W. Haywood was very kind to review and correct the
    following chapters: control, install
  
  * performance: in "Forking and Executing Subprocesses from mod_perl"
    fixed a few typos in code. (Anthony D. Ettinger, Matt Sergeant and
    Edwin Pratomo)
  
  Revision  Changes    Path
  1.21      +91 -3     modperl-site/guide/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/CHANGES,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- CHANGES	2000/02/09 21:11:39	1.20
  +++ CHANGES	2000/03/04 20:31:44	1.21
  @@ -2,8 +2,99 @@
   		### mod_perl Guide CHANGES file ###
   		###################################
   
  +03.04.2000 ver 1.21
  +
  +* help: updated the mod_perl list subscription info, added the
  +  advocacy list info.
  +
  +* download: HA section - added more links (Robin Berjon, Gerd Knops)
  +
  +* strategy: added a new section "When One Machine is not Enough for
  +  SQL DB and mod_perl" (Vivek Khera, Jeffrey W. Baker, John Armstrong,
  +  Mike Miller, Leslie Mikesell, Tom Brown, Ed Phillips, Marko van der
  +  Puil) Special thanks to Jeffrey for working on the this section
  +  before it went into the Gude.
  +
  +* perfomance: added the section "Memory Swapping is Considered Bad"
  +
  +* modules: added the Apache::GTopLimit and Apache::Watchdog::RunAway
  +  modules description
  +
  +* performance: new section "Is my Code Shared"
  +
  +* download: added links to DB sites and "Low-Cost Unix Database
  +  Differences" comparison page.
  +
  +* config: new section "Enabling Remote Server Configuration Reports"
  +
  +* performance: new section "Calculating Real Memory Usage"
  +
  +* scenario: mod_proxy section has been rewritten and extended with
  +  lots of OS specific information (Joshua Chamas, Oleg Bartunov,
  +  Gerald Richter, Radu Greab, Peter Haworth, Vivek Khera)
  +
  +* performance: rewritten "Object Methods Calls Versus Function Calls"
  +  and splitted into the original section and "Imported Symbols and
  +  Memory Usage" (James G Smith, David Mitchell, Doug, Matt Sergeant,
  +  Bill Moseley, Autarch)
  +
  +* performance: added "Reducing the Number of stat() Calls" (Steve
  +  Reppucci)
  +
  +* install: added a note of how to force CPAN shell to install mod_perl
  +  when the same version is already installed. 
  +
  +* scenario: added "mod_rewrite Examples" (Vivek Khera, Tom Mornini)
  +
  +* databases: added "Optimize: Run Two SQL Engine Servers" (Pascal
  +  Eeftinck)
  +
  +* snippets: added "Using DESTROY to Finalize Output" with solutions to
  +  redirection loghandler fixes (Michael Blakeley)
  +
  +* scenario: added to the section "One Plain and One mod_perl enabled
  +  Apache Servers" --target option to make the ./configure stage
  +  somewhat simpler. (James Furness)
  +
  +* snippets: added 2 modified versions of the mysql backup/restore
  +  scripts to work with 3.22.30+ (Ward Vandewege)
  +
  +* Moved complete files, previously enlisted in the text, to the
  +  external files. This makes the browsing faster when the files are
  +  very big.  Added new POD tag =code to create the link to the
  +  external file at the pod2html conversion stage
  +
  +* review: Ged W. Haywood was very kind to review and correct the
  +  following chapters: control, install
  +
  +* performance: in "Forking and Executing Subprocesses from mod_perl"
  +  fixed a few typos in code. (Anthony D. Ettinger, Matt Sergeant and
  +  Edwin Pratomo)
  +
  +
  +
  +
  +
   02.09.2000 ver 1.20
   
  +* I've created a mod_perl_guide package and now it's available from
  +  CPAN! So when a new version gets released you just open your CPAN
  +  shell and do:
  +
  +  % perl -MCPAN -eshell
  +  cpan> install mod_perl_guide
  +
  +  All the POD sources and build scripts has moved to this
  +  distribution, get them from CPAN. 
  +
  +* There is no more PostScript file book style distribution. A better
  +  PDF version has replaced it (suggested by Andrew Ford). Note that
  +  you can use gv (ghostview) to view pdf files, if you don't have a
  +  free acroread installed. Or you can always use 'pdf2ps' utility to
  +  convert it back to PS.
  +
  +  BTW this release's PDF file consists of 481 Letter format pages.
  +
   * install: rewritten "What Compiler Should Be Used to Build mod_perl?"
   
   * performance: added "Measuring the Subroutines Memory Usage"
  @@ -53,9 +144,6 @@
   
   * install: "make test troubleshooting": added the 'localhost' entry
     existance in '/etc/hosts' verification.
  -
  -* guide: now producing an online PDF version of the guide, following
  -  the suggestion by Andrew Ford, and not PS as I did before.
   
   * debug: explained the confusion about Sys::Signal and SIGALRM (was
     already solved internally) (Doug)
  
  
  
  1.23      +30 -7     modperl-site/guide/config.html
  
  Index: config.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/config.html,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- config.html	2000/02/09 21:11:39	1.22
  +++ config.html	2000/03/04 20:31:44	1.23
  @@ -72,6 +72,7 @@
   	</UL>
   
   	<LI><A HREF="#Validating_the_Configuration_Syn">Validating the Configuration Syntax</A>
  +	<LI><A HREF="#Enabling_Remote_Server_Configura">Enabling Remote Server Configuration Reports</A>
   	<LI><A HREF="#Publishing_Port_Numbers_Differen">Publishing Port Numbers Different from 80</A>
   	<LI><A HREF="#Configuring_Apache_mod_perl_wi">Configuring Apache + mod_perl with mod_macro</A>
   	<LI><A HREF="#General_Pitfalls">General Pitfalls</A>
  @@ -152,10 +153,10 @@
   If you didn't move Apache directories around, the installation program
   already has configured everything for you. Just start the server and test
   it working. To start the server use the <CODE>apachectl</CODE> utility which comes bundled with Apache distribution and resides in the
  -same directory with <CODE>httpd</CODE> (the Apache server itself). Go to this directory and execute:
  +same directory with <CODE>httpd</CODE> (the Apache server itself). Execute:
   
   <P>
  -<PRE>  apachectl start
  +<PRE>  /usr/local/apache/bin/apachectl start
   </PRE>
   <P>
   Now you can test the server, by trying to access it from <A
  @@ -457,10 +458,10 @@
   <P>
   Alias defines the start of the URL path to the script you are referencing.
   For example, using the above configuration, fetching
  -<EM>http://www.nowhere.com/perl/test.pl</EM>, will cause the server to look for the file <EM>test.pl</EM> at <EM>/usr/local/myproject/cgi</EM>, and execute it as an <CODE>Apache::Registry</CODE> script if we define <CODE>Apache::Registry</CODE> to be the handler of <EM>/perl</EM> location (see below).
  +<EM>http://www.example.com/perl/test.pl</EM>, will cause the server to look for the file <EM>test.pl</EM> at <EM>/usr/local/myproject/cgi</EM>, and execute it as an <CODE>Apache::Registry</CODE> script if we define <CODE>Apache::Registry</CODE> to be the handler of <EM>/perl</EM> location (see below).
   
   <P>
  -The URL <EM>http://www.nowhere.com/perl/test.pl</EM> will be mapped to
  +The URL <EM>http://www.example.com/perl/test.pl</EM> will be mapped to
   <EM>/usr/local/myproject/cgi/test.pl</EM>. This means that you can have all your CGIs located at the same place in
   the file-system, and call the script in any of three modes simply by
   changing the directory name component of the URL (<EM>cgi-bin|perl|cgi-perl</EM>) - is not this neat? (That is the configuration you see above - all three
  @@ -615,8 +616,7 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="PerlModule_and_PerlRequire_Direc">PerlModule and PerlRequire Directives</A></H2></CENTER>
   <P>
  -As we saw earlier the module should be loaded before allowed to be used,
  -the <CODE>PerlModule</CODE> and <CODE>PerlRequire</CODE> are the two mod_perl directives equivalent to the Perl's <CODE>use()</CODE>
  +As we saw earlier the module should be loaded before allowed to be used, <CODE>PerlModule</CODE> and <CODE>PerlRequire</CODE> are the two mod_perl directives equivalent to the Perl's <CODE>use()</CODE>
   and <CODE>require()</CODE> respectively. Since they are equivalent, the
   same rules apply to their arguments. You pass <CODE>Apache::DBI</CODE> as an argument for <CODE>PerlModule</CODE>, and <CODE>Apache/DBI.pm</CODE> for <CODE>PerlRequire</CODE>.
   
  @@ -1472,6 +1472,29 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Enabling_Remote_Server_Configura">Enabling Remote Server Configuration Reports</A></H1></CENTER>
  +<P>
  +A nifty mod_info module displays a complete server configuration in the
  +browser. In order to use it you have compile it in or load as an object if
  +the server was compiled with DSO mode enabled. Then uncomment the already
  +prepared section in the <EM>httpd.conf</EM> file:
  +
  +<P>
  +<PRE>  &lt;Location /server-info&gt;
  +    SetHandler server-info
  +    Order deny,allow
  +    Deny from all
  +    Allow from www.example.com
  +  &lt;/Location&gt;
  +</PRE>
  +<P>
  +Now restart the server and issue the request:
  +
  +<P>
  +<PRE>  <A HREF="http://www.example.com/server-info">http://www.example.com/server-info</A>
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Publishing_Port_Numbers_Differen">Publishing Port Numbers Different from 80</A></H1></CENTER>
   <P>
   It is advised not to publish the 8080 (or alike) port number in URLs, but
  @@ -1813,7 +1836,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/05/2000
  +	     <BR>Last Modified at 02/26/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.23      +378 -300  modperl-site/guide/control.html
  
  Index: control.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/control.html,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- control.html	2000/02/09 21:11:39	1.22
  +++ control.html	2000/03/04 20:31:45	1.23
  @@ -31,14 +31,14 @@
   	<LI><A HREF="#Using_apachectl_to_control_the_s">Using apachectl to control the server</A>
   	<LI><A HREF="#Safe_Code_Updates_on_a_Live_Prod">Safe Code Updates on a Live Production Server</A>
   	<LI><A HREF="#An_Intentional_Disabling_of_Live">An Intentional Disabling of Live Scripts</A>
  -	<LI><A HREF="#SUID_start_up_scripts">SUID start-up scripts</A>
  +	<LI><A HREF="#SUID_Start_up_Scripts">SUID Start-up Scripts</A>
   	<LI><A HREF="#Preparing_for_Machine_Reboot">Preparing for Machine Reboot</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="#Monitoring_the_Server_A_watchdo">Monitoring the Server.  A watchdog.</A>
  +	<LI><A HREF="#Running_a_Server_in_Single_Proce">Running a Server in Single Process 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_modperl_process_from_">Preventing modperl process from going wild</A>
  +	<LI><A HREF="#Preventing_mod_perl_Processes_Fr">Preventing mod_perl Processes From Going Wild</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -68,17 +68,21 @@
   <CENTER><H1><A NAME="Restarting_techniques">Restarting techniques</A></H1></CENTER>
   <P>
   All of these techniques require that you know the server PID (Process ID).
  -The easiest way to find the PID is to look it up in the <CODE>httpd.pid</CODE> file. With my configuration it exists as
  -<CODE>/usr/local/var/httpd_perl/run/httpd.pid</CODE>. It's easy to discover where to look at, by checking out the httpd.conf
  -file. Open the file and locate the entry <CODE>PidFile</CODE>:
  +The easiest way to find the PID is to look it up in the
  +<CODE>httpd.pid</CODE> file. It's easy to discover where to look at, by checking out the <EM>httpd.conf</EM> file. Open the file and locate the entry
  +<CODE>PidFile</CODE>. Here is the line from one of my own <EM>httpd.conf</EM> files:
   
   <P>
   <PRE>  PidFile /usr/local/var/httpd_perl/run/httpd.pid
   </PRE>
   <P>
  -Another way is to use the <CODE>ps</CODE> and <CODE>grep</CODE> utilities:
  +As you see, with my configuration the file is
  +<CODE>/usr/local/var/httpd_perl/run/httpd.pid</CODE>.
   
   <P>
  +Another way is to use the <CODE>ps</CODE> and <CODE>grep</CODE> utilities. Assuuming that the binary is called <EM>httpd_perl</EM>, we would do:
  +
  +<P>
   <PRE>  % ps auxc | grep httpd_perl
   </PRE>
   <P>
  @@ -87,156 +91,158 @@
   <P>
   <PRE>  % ps -ef | grep httpd_perl
   </PRE>
  +<P>
  +This will produce a list of all the <CODE>httpd_perl</CODE> (parent and 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 some other user (when you <A HREF="././install.html#Installation_Without_Superuser_P">don't have root access</A>, the processes will belong to that user unless defined differently in <EM>httpd.conf</EM>. It's still easy to find which is the parent - it's the smallest one.
  +
  +<P>
  +You will see many <CODE>httpd</CODE> executables running on your system, but you should never need to send
  +signals to any of them except the parent, whose pid is in the <EM>PidFile</EM>. There are three signals that you can send to the parent: <CODE>SIGTERM</CODE>, <CODE>SIGHUP</CODE>, and <CODE>SIGUSR1</CODE>.
  +
   <P>
  -This will produce a list of all <CODE>httpd_perl</CODE> (the parent and the children) processes. You are looking for the parent
  -process. If you run your server as root - you will easily locate it, since
  -it belongs to root. If you run the server as user (when you <A HREF="././install.html#Installation_Without_Superuser_P">don't have a root access</A>, most likely all the processes will belong to that user (unless defined
  -differently in the
  -<CODE>httpd.conf</CODE>), but it's still easy to know 'who is the parent' -- the one of the
  -smallest size...
  +Some folks prefer to specify signals using numerical values, rather than
  +using symbols. If you are looking for these, check out your
  +<CODE>kill(1)</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 SIGKILL    9    /* last resort */
  +  #define SIGTERM   15    /* software termination signal */
  +  #define SIGUSR1   30    /* user defined signal 1 */
  +</PRE>
   <P>
  -You will notice many <CODE>httpd_perl</CODE> executables running on your system, but you should not send signals to any
  -of them except the parent, whose pid is in the <CODE>PidFile</CODE>. That is to say you shouldn't ever need to send signals to any process
  -except the parent. There are three signals that you can send the parent: <STRONG>TERM</STRONG>, <STRONG>HUP</STRONG>, and <STRONG>USR1</STRONG>.
  +Note that to send these signals from the command line the <CODE>SIG</CODE>
  +prefix must be omitted.
   
   <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
  +mod_perl enabled server. See <A
   HREF="http://www.apache.org/docs/stopping.html">http://www.apache.org/docs/stopping.html</A>
  -.
  +for documentation on the implications of sending these signals to a plain
  +Apache server.
   
   <DL>
  -<P><DT><STRONG><A NAME="item_TERM">TERM Signal: stop now</A></STRONG><DD>
  +<P><DT><STRONG><A NAME="item_TERM">TERM Signal: Stop Now</A></STRONG><DD>
   <P>
  -Sending the <STRONG>TERM</STRONG> signal to the parent causes it to immediately attempt to kill off all of
  -its children. This process may take several seconds to complete, following
  -which the parent itself exits. Any requests in progress are terminated, and
  -no further requests are served.
  +Sending the <A HREF="#item_TERM">TERM</A> signal to the parent causes it immediately to attempt to kill off all its
  +children. Any requests in progress are terminated, and no further requests
  +are served. This process may take quite a few seconds to complete. To stop
  +a child, the parent sends
  +<CODE>SIGHUP</CODE> signal. If that fails it sends another. If that fails it sends <CODE>SIGTERM</CODE> signal, and as a last resort it sends <CODE>SIGKILL</CODE>
  +signal. For each failed attempt to kill a child it makes an entry in the <EM>error_log</EM>.
   
   <P>
  -That's the moment that the accumulated <CODE>END</CODE> blocks will be executed! Note that if you use <CODE>Apache::Registry</CODE> or <CODE>Apache::PerlRun</CODE>, then
  -<CODE>END</CODE> blocks are being executed upon each request (at the end).
  +Finally the parent itself exits and any open log files are closed. This is
  +when all the accumulated <CODE>END</CODE> blocks, but the ones from
  +<CODE>Apache::Registry</CODE> or <CODE>Apache::PerlRun</CODE> scripts, will be executed. The latter gets executed after each request is
  +served.
   
   <P><DT><STRONG><A NAME="item_HUP">HUP Signal: restart now</A></STRONG><DD>
   <P>
  -Sending the <STRONG>HUP</STRONG> signal to the parent causes it to kill off its children like in <STRONG>TERM</STRONG> (Any requests in progress are terminated) but the parent doesn't exit. It
  -re-reads its configuration files, and re-opens any log files. Then it
  -spawns a new set of children and continues serving hits.
  +Sending the <STRONG>HUP</STRONG> signal to the parent causes it to kill off its children as if you had sent <STRONG>TERM</STRONG> (any requests in progress are terminated) but the parent doesn't exit.
   
   <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.
  +The parent will reread its configuration files, close and re-open any log
  +files, flush all the compiled and preloaded modules, and rerun any startup
  +files. Then it spawns a new set of children and continues serving hits.
  +It's equivalent to stopping then restarting the 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.
  +Note: If your configuration files have errors when you issue a restart then
  +the parent not restart but will exit with an error and your sever will be
  +stopped. See below for a way of avoiding this.
   
   <P><DT><STRONG><A NAME="item_USR1">USR1 Signal: graceful restart</A></STRONG><DD>
   <P>
  -The <STRONG>USR1</STRONG> signal causes the parent process to advise the children to exit after their
  -current request (or to exit immediately if they're not serving anything).
  -The parent re-reads its configuration files and re-opens its log files. As
  -each child dies off the parent replaces it with a child from the new
  -generation of the configuration, which begins serving new requests
  -immediately. 
  +The <A HREF="#item_USR1">USR1</A> signal causes the parent process to advise the children to exit after
  +serving the current request, or to exit immediately if they're not serving
  +a request. 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 (the new children use the new configuration) and it begins
  +serving new requests immediately.
   
   <P>
  -The only difference between <STRONG>USR1</STRONG> and <STRONG>HUP</STRONG> is that <STRONG>USR1</STRONG> allows children to complete any in-progress request prior to killing them
  +The only difference between <A HREF="#item_USR1">USR1</A> and <A HREF="#item_HUP">HUP</A> is that <A HREF="#item_USR1">USR1</A> allows the children to complete any current requests prior to killing them
   off.
   
   <P>
  -By default, if a server is restarted (ala <CODE>kill -USR1 `cat
  -logs/httpd.pid`</CODE> or with <STRONG>HUP</STRONG> signal), Perl scripts and modules are not reloaded. To reload <STRONG>PerlRequire</STRONG>'s, <STRONG>PerlModule</STRONG>'s, other
  -<CODE>use()</CODE>'d modules and flush the <CODE>Apache::Registry</CODE> cache, enable with this command:
  +By default, if a server is restarted (using <CODE>kill -USR1 `cat
  +logs/httpd.pid`</CODE> or with the <A HREF="#item_HUP">HUP</A> signal), Perl scripts and modules are not reloaded. To reload <CODE>PerlRequire</CODE>'s, <CODE>PerlModule</CODE>'s, other
  +<CODE>use()</CODE>'d modules and flush the <CODE>Apache::Registry</CODE> cache, use this directive in <EM>httpd.conf</EM>:
   
   <P>
  -<PRE> PerlFreshRestart On              (in httpd.conf) 
  +<PRE>  PerlFreshRestart On
   </PRE>
   <P>
   Make sure you read <A HREF="././troubleshooting.html#Evil_things_might_happen_when_us">Evil things might happen when using PerlFreshRestart</A>.
   
   </DL>
  -<P>
  -It's worth mentioning that the server restart or termination can sometimes
  -take quite a lot of time. Check out the
  -<A HREF="././debug.html#PERL_DESTRUCT_LEVEL_Environment_">PERL_DESTRUCT_LEVEL</A>
  -option during the mod_perl <CODE>perl Makefile.PL</CODE> stage (or as environment variable), which speeds this up and leads to more
  -robust operation in the face of problems, like running out of memory.
  -
   <P>
  -Some folks prefer to specify signals using numerical values, rather than
  -symbolics. If you are looking for these, check out your
  -<CODE>kill(1)</CODE> man page. My page points to <CODE>/usr/include/sys/signal.h</CODE>, the relevant entries are:
  +We've already mentioned that restart or termination can sometimes take
  +quite a long time for a mod_perl server. You have an option to set the <A HREF="././debug.html#PERL_DESTRUCT_LEVEL_Environment_">PERL_DESTRUCT_LEVEL Environment Variable</A> during the <CODE>perl
  +Makefile.PL</CODE> stage. You can also simply set it to <EM>-1</EM> directly. This can speed things up, and can lead to more robust operation
  +in the face of problems such as running out of memory.
   
   <P>
  -<PRE>  #define SIGHUP     1    /* hangup, generated when terminal disconnects */ 
  -  #define SIGTERM   15    /* software termination signal */
  -  #define SIGUSR1   30    /* user defined signal 1 */
  -</PRE>
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Using_apachectl_to_control_the_s">Using apachectl to control the server</A></H1></CENTER>
   <P>
  -Apache's distribution provides a nice script to control the server. It's
  -called <STRONG>apachectl</STRONG> and it's installed into the same location with httpd. In our scenario -
  -it's
  -<CODE>/usr/local/sbin/httpd_perl/apachectl</CODE>.
  +Apache's distribution provides a script to control the server. It's called <EM>apachectl</EM> and it is installed into the same location as the httpd executable. Let's
  +say in our scenario it's in
  +<CODE>/usr/local/sbin/httpd_perl/apachectl</CODE>:
   
   <P>
  -Start httpd:
  +To start httpd_perl:
   
   <P>
   <PRE>  % /usr/local/sbin/httpd_perl/apachectl start 
   </PRE>
   <P>
  -Stop httpd:
  +To stop httpd_perl:
   
   <P>
   <PRE>  % /usr/local/sbin/httpd_perl/apachectl stop
   </PRE>
   <P>
  -Restart httpd if running by sending a <STRONG>SIGHUP</STRONG> or start if not running:
  +To restart httpd_perl (if it is running, send <CODE>SIGHUP</CODE>; if it is not already running just start it):
   
   <P>
   <PRE>  % /usr/local/sbin/httpd_perl/apachectl restart
   </PRE>
   <P>
  -Do a graceful restart by sending a <STRONG>SIGUSR1</STRONG> or start if not running:
  +Do a graceful restart by sending a <CODE>SIGUSR1</CODE>, or start if not running:
   
   <P>
   <PRE>  % /usr/local/sbin/httpd_perl/apachectl graceful    
   </PRE>
   <P>
  -Do a configuration syntax test:
  +To do a configuration test:
   
   <P>
   <PRE>  % /usr/local/sbin/httpd_perl/apachectl configtest 
   </PRE>
  +<P>
  +Replace <CODE>httpd_perl</CODE> with <CODE>httpd_docs</CODE> in the above calls to control the <CODE>httpd_docs</CODE> server.
  +
   <P>
  -Replace <CODE>httpd_perl</CODE> with <CODE>httpd_docs</CODE> in the above calls to control the <STRONG>httpd_docs</STRONG> server.
  +There are other options for <CODE>apachectl</CODE>, use the <CODE>help</CODE> option to see them all.
   
   <P>
  -There are other options for <STRONG>apachectl</STRONG>, use <CODE>help</CODE> option to see them all.
  +It's important to remember that <CODE>apachectl</CODE> uses the PID file, which is specified by the <CODE>PIDFILE</CODE> directive in <CODE>httpd.conf</CODE>. If you delete the PID file by hand, <STRONG>apachectl</STRONG> will fail to run.
   
   <P>
  -It's important to understand that this script is based on the PID file
  -which is <CODE>PIDFILE=/usr/local/var/httpd_perl/run/httpd.pid</CODE>. If you delete the file by hand - <STRONG>apachectl</STRONG> will fail to run.
  +Also note that <EM>apachectl</EM> is suitable for use from within a Unix system's startup files so that the
  +Web server is automatically restarted at system reboot.
   
   <P>
  -Also, notice that <STRONG>apachectl</STRONG> is suitable to use from within your Unix system's startup files so that
  -your web server is automatically restarted upon system reboot. Either copy
  -the <STRONG>apachectl</STRONG> file to the appropriate location (<CODE>/etc/rc.d/rc3.d/S99apache</CODE> works on my RedHat Linux system) or create a symlink with that name
  +Either copy the <EM>apachectl</EM> 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 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.)
  +script is writable only by root! The startup scripts have root privileges
  +during initialisation, and you don't want to open any security holes.)
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -248,15 +254,15 @@
   code.
   
   <P>
  -It's quite easy to prevent it! Just don't overwrite the previous good
  -files!!! 
  +It's quite easy to prevent it, just don't overwrite the previous good
  +files!
   
   <P>
  -Personally I do all updates on the live server with a following sequence.
  -Assume that the root directory lies in
  +Personally I do all updates on the live server with the following sequence.
  +Assume that the server root directory is
   <CODE>/home/httpd/perl/rel</CODE>. When I'm about to update the files I create a new directory <CODE>/home/httpd/perl/beta</CODE>, copy the old files from
  -<CODE>/home/httpd/perl/rel</CODE> and update it with new files I'm about to replace. Then I do last sanity
  -checks (file permissions (read+executable), run <CODE>perl -c</CODE> on the new modules to make sure there no errors in them). When I think I'm
  +<CODE>/home/httpd/perl/rel</CODE> and update it with the new files. Then I do some last sanity checks (check
  +file permissions are [read+executable], and run <CODE>perl -c</CODE> on the new modules to make sure there no errors in them). When I think I'm
   ready I do:
   
   <P>
  @@ -264,73 +270,122 @@
     % mv rel old &amp;&amp; mv beta rel &amp;&amp; stop &amp;&amp; sleep 3 &amp;&amp; restart &amp;&amp; err
   </PRE>
   <P>
  -Let's explain what I'm doing. First I use alises to make things faster:
  +Let me explain what I'm doing.
   
   <P>
  +Firstly, note that I put all the commands on one line, separated by
  +<CODE>&amp;&amp;</CODE>, and only then press the <CODE>Enter</CODE> key. As I am working remotely, this ensures that if I suddenly get a lost
  +connection (sadly that happens sometimes) I won't leave the server down if
  +only the
  +<CODE>stop</CODE> command squeezed in.  <CODE>&amp;&amp;</CODE> also ensures that if any command fails, the rest won't be executed. I am
  +using aliases (which I have already defined) to make the typing easier:
  +
  +<P>
   <PRE>  % alias | grep apachectl
  -  graceful        /usr/local/apache/bin/apachectl graceful
  +  graceful /usr/local/apache/bin/apachectl graceful
     rehup   /usr/local/apache/sbin/apachectl restart
     restart /usr/local/apache/bin/apachectl restart
     start   /usr/local/apache/bin/apachectl start
     stop    /usr/local/apache/bin/apachectl stop
  -  
  -  % alias err
  +</PRE>
  +<P>
  +<PRE>  % alias err
     tail -f /usr/local/apache/logs/error_log
   </PRE>
   <P>
  -So I write all the commands in one line, separated with <CODE>&amp;&amp;</CODE> and only then press <CODE>Enter</CODE> key. That ensures that if I suddenly get a connection lost (sadly but that
  -happens sometimes) I wouldn't leave the server down if only the <CODE>stop</CODE> command squeezed in. <CODE>&amp;&amp;</CODE> ensures that if any command has failed the rest won't be executed.
  +Taking the line apart piece by piece:
   
   <P>
  -I backup the old working directory in <CODE>old</CODE>, and move the new one instead. I stop the server, give it a few seconds to
  -shutdown (it might take even longer) and then do <CODE>restart</CODE> followed by immediate view of the tail of the <CODE>error_log</CODE> file in order to see that everything is OK. <CODE>apachectl</CODE> generates the status messages too early (e.g. on <CODE>stop</CODE> it says server has been stopped, while it's not yet, so don't rely on it,
  -rely on <CODE>error_log</CODE> file instead). Also you have noticed that I use <CODE>restart</CODE> and not just <CODE>start</CODE>. I do this for the same reason of Apache's long stopping times (it depends
  -on what you do with it of course!), so if you use <CODE>start</CODE> and Apache didn't release the port it listens to, the start would fail and <CODE>error_log</CODE> would tell that port is in use, e.g.:
  +mv rel old &amp;&amp;
   
   <P>
  +<PRE>  back up the working directory to C&lt;old&gt;
  +</PRE>
  +<P>
  +mv beta rel &amp;&amp;
  +
  +<P>
  +<PRE>  put the new one in its place
  +</PRE>
  +<P>
  +stop &amp;&amp;
  +
  +<P>
  +<PRE>  stop the server
  +</PRE>
  +<P>
  +sleep 3 &amp;&amp;
  +
  +<P>
  +<PRE>  give it a few seconds to shut down (it might take even longer)
  +</PRE>
  +<P>
  +restart &amp;&amp;
  +
  +<P>
  +<PRE>  C&lt;restart&gt; the server
  +</PRE>
  +<P>
  +err
  +
  +<P>
  +<PRE>  view of the tail of the C&lt;error_log&gt; file in order to see that
  +  everything is OK
  +</PRE>
  +<P>
  +<CODE>apachectl</CODE> generates the status messages a little too early (e.g. when you issue <CODE>apachectl stop</CODE> it says the server has been stopped, while in fact it's still running) so
  +don't rely on it, rely on the <CODE>error_log</CODE> file instead.
  +
  +<P>
  +Also you have noticed that I use <CODE>restart</CODE> and not just <CODE>start</CODE>. I do this because of Apache's potentially long stopping times (it depends
  +on what you do with it of course!). If you use <CODE>start</CODE> and Apache hasn't yet releases the port it's listening to, the start would
  +fail and <CODE>error_log</CODE> would tell you that port is in use, e.g.:
  +
  +<P>
   <PRE>  Address already in use: make_sock: could not bind to port 8080
   </PRE>
   <P>
  -But if you use <CODE>restart</CODE>, it will patiently wait for the server to quit and then will cleanly start
  -it.
  +But if you use <CODE>restart</CODE>, it will wait for the server to quit and then will cleanly restart it.
   
   <P>
   Now what happens if the new modules are broken? First of all, I see
  -immediately the indication of the problems reported at <CODE>error_log</CODE>
  -file, which I <CODE>tail -f</CODE> immediately after a restart command. That's easy, we just put everything as
  -it was before:
  +immediately an indication of the problems reported in the <CODE>error_log</CODE>
  +file, which I <CODE>tail -f</CODE> immediately after a restart command. If there's a problem, I just put
  +everything as it was before:
   
   <P>
   <PRE>  % mv rel bad &amp;&amp; mv old rel &amp;&amp; stop &amp;&amp; sleep 3 &amp;&amp; restart &amp;&amp; err
   </PRE>
   <P>
  -And 99.9% that everything would be alright, and you have had only about 10
  -secs of downtime, which is pretty good!
  +Usually everything will be fine, and I have had only about 10 seconds of
  +downtime, which is pretty good!
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="An_Intentional_Disabling_of_Live">An Intentional Disabling of Live Scripts</A></H1></CENTER>
  +<P>
  +What happens if you really must take down the server or disable the
  +scripts? This situation might happen when you need to do some maintenance
  +work on your database server. If you have to take it down the scripts using
  +this database server will fail.
  +
   <P>
  -What happens if you really must took down the server or disable the
  -scripts? This situation might happen when you need to do some maintanance
  -works on your database server, which you have to put down and which cause
  -all the scripts using this database server non-working. If you do nothing,
  -user will see either grey <CODE>The Error
  -has happened</CODE> or a better customized error message if you have added a code to trap and
  -customize the errors (See <A HREF="././snippets.html#Redirecting_Errors_to_the_Client">Redirecting Errors to the Client instead of error_log</A>
  -for the latter case)
  -
  -<P>
  -A much more user friendly approach is to confess to your users that you are
  -doing some maintainance works and plead for a paitience, promising that the
  -services will become fully functional in X minutes (it worth to keep the
  -promize!). There are a few ways to do that:
  +If you do nothing, the user will see either the grey <CODE>An Error has
  +happened</CODE> message or perhaps a customized error message if you have added code to
  +trap and customize the errors. See <A HREF="././snippets.html#Redirecting_Errors_to_the_Client">Redirecting Errors to the Client instead of to the error_log</A> for the latter case.
   
   <P>
  -First doesn't require messing with server and works when you have to
  -disable a script and not a module! Just prepare a little script like:
  +A much more friendlier approach is to confess to your users that you are
  +doing some maintenance work and plead for patience, promising (keep the
  +promise!) that the service will become fully functional in X minutes. There
  +are a few ways to do this:
   
   <P>
  +The first doesn't require messing with the server. It works when you have
  +to disable a script, but not a module! Just prepare a little script like
  +this:
  +
  +<P>
   <PRE>  /home/http/perl/construction.pl
     ----------------------------
     #!/usr/bin/perl -wT
  @@ -339,13 +394,13 @@
     use CGI;
     my $q = new CGI;
     print $q-&gt;header,
  -  &quot;Sorry, the service is down for maintainance. 
  -   It will be back in a about 5-15 minutes.
  +  &quot;Sorry, the service is temporarily down for maintenance. 
  +   It will be back in ten to fifteen minutes.
      Please, bear with us.
      Thank you!&quot;;
   </PRE>
   <P>
  -And if now you have to disable a script at <CODE>/home/http/perl/chat.pl</CODE>, just do:
  +And if now you have to disable a script at <CODE>/home/http/perl/chat.pl</CODE>, just do this:
   
   <P>
   <PRE>  % mv /home/http/perl/chat.pl /home/http/perl/chat.pl.orig
  @@ -353,28 +408,37 @@
   </PRE>
   <P>
   Of course you server configuration should allow symbolic links for this
  -trick to work. Just make sure you have
  +trick to work. Make sure you have the directive
   
   <P>
   <PRE>  Options FollowSymLinks
   </PRE>
   <P>
  -directive in your <CODE>&lt;Location</CODE>&gt;/<CODE>&lt;Directory</CODE>&gt; section configuration.
  +in the <CODE>&lt;Location</CODE>&gt; or <CODE>&lt;Directory</CODE>&gt; section of your <CODE>httpd.conf</CODE>.
   
   <P>
  -When done, it's easy to restore the previous setup. Just do:
  +When you're done, it's easy to restore the previous setup. Just do this:
   
   <P>
   <PRE>  % mv /home/http/perl/chat.pl.orig /home/http/perl/chat.pl
   </PRE>
  +<P>
  +which overwrites the symbolic link.
  +
  +<P>
  +Now make sure that the script will have the current timestamp:
  +
  +<P>
  +<PRE>  % touch /home/http/perl/chat.pl
  +</PRE>
   <P>
  -and overwrite the symbolic link. Apache will automatically detect the
  -change and will use the moved script instead.
  +Apache will automatically detect the change and will use the moved script
  +instead.
   
   <P>
  -Second approach, is changing the server configuration and configure a whole
  -directories to be handled by Contruction handler that you would write, e.g.
  -if you write something like:
  +The second approach is to change the server configuration and configure a
  +whole directory to be handled by a <CODE>Construction</CODE> handler (which you must write). For example if you write something like
  +this:
   
   <P>
   <PRE>  Construction.pm
  @@ -385,15 +449,15 @@
     sub handler{
       my $q = new CGI;
       print $q-&gt;header,
  -    &quot;Sorry, the service is down for maintainance. 
  -     It will be back in a about 5-15 minutes.
  -     Please, bear with us.
  -     Thank you!&quot;;
  +  &quot;Sorry, the service is temporarily down for maintenance. 
  +   It will be back in ten to fifteen minutes.
  +   Please, bear with us.
  +   Thank you!&quot;;
       return OK;
     }
   </PRE>
   <P>
  -and put it in directory that in the server's <CODE>@INC</CODE>, to put down all your scripts at <CODE>/perl</CODE> you would replace:
  +and put it in a directory that in the server's <CODE>@INC</CODE>, to disable all the scripts in Location <CODE>/perl</CODE> you would replace:
   
   <P>
   <PRE>  &lt;Location /perl&gt;
  @@ -413,9 +477,9 @@
     &lt;/Location&gt;
   </PRE>
   <P>
  -Now restart the server and your user will be happy to know that you are
  -working on a much better version of the service and it worth for them to go
  -read slashdot.org and come back in 10 minutes.
  +Now restart the server. Your user will be happy to go and read slashdot.org
  +for ten minutes, knowing that you are working on a much better version of
  +the service.
   
   <P>
   If you need to disable a location handled by some module, the second
  @@ -423,13 +487,14 @@
   
   <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>
  +<CENTER><H1><A NAME="SUID_Start_up_Scripts">SUID Start-up Scripts</A></H1></CENTER>
   <P>
  -For those who wants to use <STRONG>SUID</STRONG> startup script, here is an example for you. This script is <STRONG>SUID</STRONG> to <STRONG>root</STRONG>, and should be executable only by members of some special group at your
  -site. Note the 10th line, which ``fixes an obscure error when starting
  -apache/mod_perl'' by setting the real to the effective UID. As others have
  -pointed out, it is the mismatch between the real and the effective UIDs
  -that causes Perl to croak on the -e switch.
  +For those who want to use SUID startup scripts, here is an example. This
  +script is SUID <EM>root</EM>, and should be executable only by members of some special group at your
  +site. Note the tenth line, which fixes an obscure error when starting
  +apache/mod_perl by setting the real to the effective UID. As others have
  +pointed out, a mismatch between the real and the effective UIDs causes Perl
  +to croak on the -e switch.
   
   <P>
   Note that you must be using a version of Perl that recognizes and emulates
  @@ -486,27 +551,29 @@
   <CENTER><H1><A NAME="Preparing_for_Machine_Reboot">Preparing for Machine Reboot</A></H1></CENTER>
   <P>
   When you run your own development box, it's OK to start the webserver by
  -hand when you need it. On the production system, there is chance that the
  -machine the server is running on will have to be rebooted. Once the reboot
  -is completed, who is going to rememeber to start the server? It's an easy
  -to forget task, and what happens if you aren't around when the machine was
  +hand when you need it. On a production system, there is chance that the
  +machine the server is running on will have to be rebooted. When the reboot
  +is completed, who is going to rememeber to start the server? It's easy to
  +forget this task, and what happens if you aren't around when the machine is
   rebooted?
   
   <P>
   After the server installation is complete, it's important not to forget
  -that you need to put a script, to perform the server startup and shutdown,
  -into a standard system location, like
  -<CODE>/etc/rc.d/init.d</CODE> or equivalent (varies from OS to OS). This is the directory where all other
  -daemons are being started and shutted down from.
  +that you need to put a script to perform the server startup and shutdown
  +into the standard system location, for example <CODE>/etc/rc.d</CODE>.
   
   <P>
  -Generally the simplest solution is to copy there the apachectl script, that
  -you will find in the same directory with httpd executable after Apache
  -installation. If you have more than one Apache server, you have to put a
  -script for each one, of course renaming them on the way. 
  +This is the directory which contains scripts to start and stop all the
  +other daemons. The directory and file names vary from one Operating System
  +to another, and even between different distributions of the same OS.
   
   <P>
  -For example on Linux RedHat machine with two server setup, I've the
  +Generally the simplest solution is to copy the <CODE>apachectl</CODE> script to your startup directory. You will find <CODE>apachectl</CODE> in the same directory as the httpd executable after Apache installation. If
  +you have more than one Apache server you need a script for each one, and of
  +course you will have to rename them.
  +
  +<P>
  +For example on a RedHat Linux machine with two servers, I have the
   following setup:
   
   <P>
  @@ -518,42 +585,43 @@
     /etc/rc.d/rc6.d/K87httpd_perl -&gt; ../init.d/httpd_perl
   </PRE>
   <P>
  -In &lt;init.d&gt; directory reside the scripts themselves. In the rest of
  -directories reside the symbolic links to these scripts, prepended with
  -numbers to preserve a particular order of execution.
  +The scripts themselves reside in the <EM>init.d</EM> directory. There are symbolic links to these scripts in other directories,
  +the names are the same as the script names but they have numbers prepended,
  +which used for executing the scripts in a particular order: the lower
  +numbers are executed earlier.
   
   <P>
  -When a machine is booted and its runlevel set as 3 (multiuser+network),
  -Linux goes into <CODE>/etc/rc.d/rc3.d/</CODE> and executes the scripts the symbolic links point to with the <CODE>start</CODE> argument, so when it sees the <EM>S87httpd_perl</EM>, it executes:
  +When a machine is booted and its runlevel set to 3 (multiuser+network),
  +Linux goes into <CODE>/etc/rc.d/rc3.d/</CODE> and executes the scripts the symbolic links point to with the <CODE>start</CODE> argument. When it sees <EM>S87httpd_perl</EM>, it executes:
   
   <P>
   <PRE>  /etc/rc.d/init.d/httpd_perl start
   </PRE>
   <P>
  -When the machine is being shutted down, the scripts pointed from
  -<EM>/etc/rc.d/rc6.d/</EM> directory are being executed, this time the scripts are called with <CODE>stop</CODE> argument, like:
  +When the machine is shut down, the scripts are executed through links from
  +the <EM>/etc/rc.d/rc6.d/</EM> directory. This time the scripts are called with the <CODE>stop</CODE> argument, like this:
   
   <P>
   <PRE>  /etc/rc.d/init.d/httpd_perl stop
   </PRE>
   <P>
  -Most of the systems are coming with GUI utilites to automate the symbolic
  -links creation. For example Linux RH includes a
  -<CODE>control-panel</CODE> utility, which among other utilities includes a
  -<CODE>RunLevel Manager</CODE> that will help you to properly create the symbolic links. Of course before
  -you use it, you should put the <CODE>apachectl</CODE> or similar scripts into a <EM>init.d</EM> or equivalent directory.
  +Most of the systems have GUI utilites to automate the creation of symbolic
  +links. For example RedHat Linux includes the
  +<CODE>control-panel</CODE> utility, which amongst other things includes the
  +<CODE>RunLevel Manager</CODE>. This will help you to create the proper symbolic links. Of course before
  +you use it, you should put <CODE>apachectl</CODE> or similar scripts into the <EM>init.d</EM> or equivalent directory.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Monitoring_the_Server_A_watchdo">Monitoring the Server. A watchdog.</A></H1></CENTER>
  +<CENTER><H1><A NAME="Monitoring_the_Server_A_watchdo">Monitoring the Server.  A watchdog.</A></H1></CENTER>
   <P>
  -With mod_perl many things can happen to your server. The worst one is the
  -possibility that the server will die when you will be not around. As with
  -any other critical service you need to run some kind of watchdog.
  +With mod_perl many things can happen to your server. It is possibile that
  +the server might die when you are not around. As with any other critical
  +service you need to run some kind of watchdog.
   
   <P>
  -One simple solution is to use a slightly modified <STRONG>apachectl</STRONG> script, which I've named it <EM>apache.watchdog</EM>. Call it from the crontab every 30 minutes or even every minute - if it's
  -so critical to make sure the server will be up all the time.
  +One simple solution is to use a slightly modified <STRONG>apachectl</STRONG> script, which I've named <EM>apache.watchdog</EM>. Call it from the crontab every 30 minutes -- or even every minute -- to
  +make sure the server is up all the time.
   
   <P>
   The crontab entry for 30 minutes intervals:
  @@ -568,8 +636,8 @@
   <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 
  +  # It tries to restart the server, and if it's
  +  # down it sends an email alert to admin 
     
     # admin's email
     EMAIL=webmaster@somewhere.far
  @@ -610,26 +678,26 @@
   </PRE>
   <P>
   Another approach, probably even more practical, is to use the cool
  -<CODE>LWP</CODE> perl package , to test the server by trying to fetch some document (script)
  -served by the server. Why is it more practical? Because, while the server
  -can be up as a process, it can be stuck and not working, So failing to get
  -the document will trigger restart, and ``probably'' the problem will go
  -away. (Just replace <CODE>start</CODE> with
  +<CODE>LWP</CODE> perl package to test the server by trying to fetch some document (script)
  +served by the server. Why is it more practical? Because while the server
  +can be up as a process, it can be stuck and not working. Failing to get the
  +document will trigger restart, and ``probably'' the problem will go away.
  +Just replace <CODE>start</CODE> with
   <CODE>restart</CODE> in the <CODE>$restart_command</CODE> below.
   
   <P>
  -Again we put this script into a crontab to call it every 30 minutes.
  +Again we put this script into the crontab to call it every 30 minutes.
   Personally I call it every minute, to fetch some very light script. Why so
  -often? If your server starts to spin and trash your disk's space with
  -multiply error messages, in a 5 minutes you might run out of free space,
  -which might bring your system to its knees. And most chances that no other
  -child will be able to serve requests, since the system will be too busy,
  -writing to an <CODE>error_log</CODE> file. Think big -- if you are running a heavy service, which is very fast,
  -since you are running under mod_perl, adding one more request every minute,
  -will be not felt by the server at all.
  +often? If your server starts to spin and trash your disk space with
  +multiple error messages, in five minutes you might run out of free disk
  +space which might bring your system to its knees. Chances are that no other
  +child will be able to serve requests, since the system will be too busy
  +writing to the <CODE>error_log</CODE> file. Think big -- if you are running a heavy service (which is very fast
  +since you are running under mod_perl) adding one more request every minute
  +will not be felt by the server at all.
   
   <P>
  -So we end up with crontab entry:
  +So we end up with a crontab entry like this:
   
   <P>
   <PRE>  * * * * * /path/to/the/watchdog.pl &gt;/dev/null 2&gt;&amp;1
  @@ -669,8 +737,8 @@
     # 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. 
  +  # Houston, we have a problem.
  +  # The server seems to be down, try to restart it. 
     my $status = system $restart_command;
     #  print &quot;Status $status\n&quot;;
     
  @@ -688,7 +756,7 @@
     send_mail($from,$to,$subject,$message);
     
     # input:  URL to check 
  -  # output: 1 if success, o for fail  
  +  # output: 1 for success, 0 for failure
     #######################  
     sub checkurl{
       my ($url) = @_;
  @@ -703,7 +771,7 @@
       return 0;
     } #  end of sub checkurl
     
  -  # sends email about the problem 
  +  # send email about the problem 
     #######################  
     sub send_mail{
       my($from,$to,$subject,$messagebody) = @_;
  @@ -725,65 +793,72 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Running_server_in_a_single_mode">Running server in a single mode</A></H1></CENTER>
  +<CENTER><H1><A NAME="Running_a_Server_in_Single_Proce">Running a Server in Single Process Mode</A></H1></CENTER>
   <P>
   Often while developing new code, you will want to run the server in single
  -process mode. See <A HREF="././porting.html#Sometimes_it_Works_Sometimes_it">Sometimes it works Sometimes it does Not</A> and <A HREF="././porting.html#Name_collisions_with_Modules_and">Names collisions with Modules and libs</A>
  -Running in single process mode inhibits the server from ``daemonizing'',
  -allowing you to run it more easily under debugger control.
  +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'',
  +and this allows you to run it under the control of a debugger more easily.
   
   <P>
   <PRE>  % /usr/local/sbin/httpd_perl/httpd_perl -X
   </PRE>
   <P>
  -When you execute the above the server will run in the fg (foreground) of
  -the shell you have called it from. So to kill you just kill it with
  -<STRONG>Ctrl-C</STRONG>.
  +When you use the -X switch the server will run in the foreground of the
  +shell, so you can kill it with <EM>Ctrl-C</EM>.
   
   <P>
  -Note that in <CODE>-X</CODE> mode the server will run very slowly while fetching images. If you use
  -Netscape while your server is running in single-process mode, HTTP's <CODE>KeepAlive</CODE> feature gets in the way. Netscape tries to open multiple connections and
  +Note that in <CODE>-X</CODE> (single-process) mode the server will run very slowly while fetching
  +images.
  +
  +<P>
  +Note for Netscape users:
  +
  +<P>
  +If you use Netscape while your server is running in single-process mode,
  +HTTP's <CODE>KeepAlive</CODE> feature gets in the way. Netscape tries to open multiple connections and
   keep them open. Because there is only one server process listening, each
  -connection has to time-out before the next succeeds. Turn off
  -<CODE>KeepAlive</CODE> in <CODE>httpd.conf</CODE> to avoid this effect while developing or you can press <STRONG>STOP</STRONG> after a few seconds (assuming you use the image size params, so the
  -Netscape will be able to render the rest of the page).
  +connection has to time out before the next succeeds. Turn off <CODE>KeepAlive</CODE> in <CODE>httpd.conf</CODE> to avoid this effect while developing. If you use the image size
  +parameters, Netscape will be able to render the page without the images so
  +you can press the browser's <EM>STOP</EM> button after a few seconds.
   
   <P>
  -In addition you should know that when running with <CODE>-X</CODE> you will not see any control messages that the parent server normally
  -writes to the error_log. (Like ``server started, server stopped and etc''.)
  -Since
  -<CODE>httpd -X</CODE> causes the server to handle all requests itself, without forking any
  -children, there is no controlling parent to write status messages.
  +In addition you should know that when running with <CODE>-X</CODE> you will not see the control messages that the parent server normally
  +writes to the error_log (<EM>"server started", "server stopped"</EM> 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 the status messages.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Starting_a_personal_server_for_e">Starting a personal server for each developer</A></H1></CENTER>
  +<CENTER><H1><A NAME="Starting_a_Personal_Server_for_E">Starting a Personal Server for Each Developer</A></H1></CENTER>
  +<P>
  +If you are the only developer working on the specific server:port you have
  +no problems, since you have complete control over the server. However,
  +often you will have a group of developers who need to develop mod_perl
  +scripts and modules concurrently. This means that each developer will want
  +to have control over the server - to kill it, to run it in single server
  +mode, to restart it etc., as well as having control over the location of
  +the log files, configuration settings like <CODE>MaxClients</CODE>, and so on.
  +
   <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:
  +You <EM>can</EM> work around this problem by preparing a few <EM>httpd.conf</EM>
  +files and forcing each developer to use
   
   <P>
   <PRE>  httpd_perl -f /path/to/httpd.conf  
   </PRE>
   <P>
  -I have approached it in other way. I have used the <CODE>-Dparameter</CODE>
  +but I approach it in a different way. I use the <CODE>-Dparameter</CODE>
   startup option of the server. I call my version of the server
   
   <P>
   <PRE>  % http_perl -Dsbekman
   </PRE>
   <P>
  -In <CODE>httpd.conf</CODE> I wrote:
  +In <EM>httpd.conf</EM> I write:
   
   <P>
   <PRE>  # Personal development Server for sbekman
  -  # sbekman use the server running on port 8000
  +  # sbekman uses the server running on port 8000
     &lt;IfDefine sbekman&gt;
     Port 8000
     PidFile /usr/local/var/httpd_perl/run/httpd.pid.sbekman
  @@ -813,25 +888,24 @@
     &lt;/IfDefine&gt;
   </PRE>
   <P>
  -What we have achieved with this technique: Full control over start/stop,
  -number of children, separate error log file, and port selection. This saves
  -me from getting called every few minutes - ``Stas, I'm going to restart the
  -server''.
  +With this technique we have achieved for each server full control over
  +start/stop, number of children, a separate error log file, and port
  +selection. This saves me from getting called every few minutes - ``Stas,
  +I'm going to restart the server''.
   
   <P>
  -To make things even easier. (In the above technique, you have to discover
  -the PID of your parent <CODE>httpd_perl</CODE> process - written in
  -<CODE>/usr/local/var/httpd_perl/run/httpd.pid.userfoo</CODE>) . We change the
  -<STRONG>apachectl</STRONG> script to do the work for us. We make a copy for each developer called <STRONG>apachectl.username</STRONG> and we change 2 lines in script:
  +In the above technique, you need to discover the PID of your parent
  +<CODE>httpd_perl</CODE> process, which is written in
  +<CODE>/usr/local/var/httpd_perl/run/httpd.pid.userfoo</CODE>. To make things even easier we change the <EM>apachectl</EM> script to do the work for us. We make a copy for each developer called <STRONG>apachectl.username</STRONG> and we change two lines in each script:
   
   <P>
   <PRE>  PIDFILE=/usr/local/var/httpd_perl/run/httpd.pid.sbekman
     HTTPD='/usr/local/sbin/httpd_perl/httpd_perl -Dsbekman'
   </PRE>
   <P>
  -Of course you think you can use only one control file and know who is
  -calling by using uid, but since you have to be root to start the server -
  -it is not so simple.
  +You might think you can use only one control file and know who is calling
  +from the uid, but since you have to be root to start the server it is not
  +so simple.
   
   <P>
   The last thing was to let developers an option to run in single process
  @@ -842,13 +916,13 @@
   </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:
  +everywhere in the static documents, including the calls to CGIs. You may
  +ask how using relative links will get to the right server. It's very
  +simple, we use <CODE>mod_rewrite</CODE>.
   
   <P>
  -In <CODE>access.conf</CODE> of the <CODE>httpd_docs</CODE> server we have the following code: (you have to configure your <CODE>httpd_docs</CODE> server with
  -<CODE>--enable-module=rewrite</CODE> )
  +To use mod_rewrite you have to configure your <EM>httpd_docs</EM> server with <CODE>--enable-module=rewrite</CODE> and recompile, or use DSO and load the module in httpd.conf. In the <EM>access.conf</EM> of our <CODE>httpd_docs</CODE>
  +server we have the following code:
   
   <P>
   <PRE>  # sbekman' server
  @@ -869,23 +943,28 @@
     
   </PRE>
   <P>
  -where IP numbers are the IPs of the developer client machines (where they
  -are running their web browser.) (I have tried to use
  -<CODE>REMOTE_USER</CODE> since we have all the users authenticated but it did not work for me)
  +the IP addresses are the addresses of the developer client machines (where
  +they are running their web browsers). I tried to use
  +<CODE>REMOTE_USER</CODE> since we have all the users authenticated but it did not work for me.
   
   <P>
  -So if I have a relative URL like <CODE>/perl/test.pl</CODE> written in some html or even <CODE>http://www.nowhere.com/perl/test.pl</CODE> in my case (user at machine of <CODE>sbekman</CODE>) it will be redirected by <CODE>httpd_docs</CODE> to
  -<CODE>http://www.nowhere.com:8000/perl/test.pl</CODE>.
  +So if written in some <EM>file.html</EM> I have a relative URL like
  +<EM>/perl/test.pl</EM> or even <A
  +HREF="http://www.nowhere.com/perl/test.pl">http://www.nowhere.com/perl/test.pl</A>
  +(the user at the machine of <EM>sbekman</EM>) it will be redirected by httpd_docs to <A
  +HREF="http://www.nowhere.com:8000/perl/test.pl.">http://www.nowhere.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:
  +You have another problem: the CGI script may generate some html which the
  +client may then use to request further action from the server. If the
  +script generates a URL with a hard coded PORT, the above scheme will not
  +work. There two solutions:
   
   <P>
  -First, generate relative URL so it will reuse the technique above, with
  -redirect (which is transparent for user) but it will not work if you have
  -something to <CODE>POST</CODE> (redirect looses all the data!).
  +First, generate relative URLs so it will reuse the technique above, with
  +redirect (which is transparent for the user). But this will not work if you
  +have something to <CODE>POST</CODE>, because the redirect loses all the data!
   
   <P>
   Second, use a general configuration module which generates a correct full
  @@ -895,41 +974,43 @@
   
   <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.
  +production, since if you have a static form and the <CODE>Action</CODE> is relative but the static document is located on another server, pressing
  +the form's submit will cause a redirect to the mod_perl server and 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>
  +<CENTER><H1><A NAME="Wrapper_to_Emulate_the_Server_En">Wrapper to Emulate the Server Environment</A></H1></CENTER>
   <P>
  -Many times you start off debugging your script by running it from your
  -favorite shell. Sometimes you encounter a very weird situation when script
  -runs from the shell but dies when called as a CGI. The real problem lies in
  -the difference between the environment that is being used by your server
  -and your shell. An example can be a different perl path or having <CODE>PERL5LIB</CODE> env variable which includes paths that are not in the <CODE>@INC</CODE> of the perl compiled with mod_perl server and configured during the
  -startup.
  +Often you will start off debugging your script by running it from your
  +favorite shell. Sometimes you encounter a very weird situation when the
  +script runs from the shell but dies when called as a CGI. The real problem
  +often lies in the difference between the environment that is used by your
  +server and the one used by your shell. For example you may have a different
  +Perl path, a <CODE>PERL5LIB</CODE> environment variable which includes paths that are not in the <CODE>@INC</CODE> array of the copy of Perl which is linked into the mod_perl server and
  +configured during startup.
   
   <P>
   The best debugging approach is to write a wrapper that emulates the exact
  -environment of the server, by first deleting the environment variables like <CODE>PERL5LIB</CODE> and calling the same perl binary that it is being used by the server. Next,
  -set the environment identical to the server's by copying the perl run
  -directives from server startup and configuration files. It will also allow
  -you to remove completely the first line of the script - since mod_perl
  +environment of the server, first deleting environment variables like <CODE>PERL5LIB</CODE> and then 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 the server startup and configuration files. This will also
  +allow you to remove completely the first line of the script, since mod_perl
   skips it and the wrapper knows how to call the script.
   
   <P>
  -Below is the example of such a script. Note that we force the <CODE>-Tw</CODE>
  -when we call the real script. (I have also added the ability to pass
  -params, which will not happen when you call the cgi from the web)
  +Below is the example of such a script. Note that we force the use of
  +<CODE>-Tw</CODE> when we call the real script. I have also added the ability to pass
  +parameters, which will not happen when you call the CGI script from the
  +Web.
   
   <P>
   <PRE>  #!/usr/local/bin/perl -w    
      
     # This is a wrapper example 
      
  -  # It simulates the web server environment by setting the @INC and other
  -  # stuff, so what will run under this wrapper will run under web and
  +  # It simulates the web server environment by setting @INC and other
  +  # stuff, so what will run under this wrapper will run under Web and
     # vice versa. 
     
     #
  @@ -975,19 +1056,19 @@
     }
     
       # run the cgi from the script's directory
  -    # Note that we invoke warnings and Taint mode ON!!!
  +    # Note that we set Warning and Taint modes 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...
  +A little bit off topic, but useful to know and use with mod_perl where your
  +error_log can grow at 10-100Mb per day if your scripts spit out lots of
  +warnings...
   
   <P>
  -To rotate the logs do:
  +To rotate the logs do this:
   
   <P>
   <PRE>  mv access_log access_log.renamed
  @@ -1007,7 +1088,7 @@
   <P>
   <PRE>  #!/usr/local/bin/perl -Tw
     
  -  # this script does a log rotation. Called from crontab.
  +  # This script does log rotation. Called from crontab.
     
     use strict;
     $ENV{PATH}='/bin:/usr/bin';
  @@ -1021,7 +1102,7 @@
     my $gzip_exec = &quot;/usr/bin/gzip&quot;;
     
     my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
  -  my $time = sprintf &quot;%0.2d.%0.2d.%0.2d-%0.2d.%0.2d.%0.2d&quot;, $year,++$mon,$mday,$hour,$min,$sec;
  +  my $time = sprintf &quot;%0.4d.%0.2d.%0.2d-%0.2d.%0.2d.%0.2d&quot;, $year+1900,++$mon,$mday,$hour,$min,$sec;
     $^I = &quot;.&quot;.$time;
     
     # rename log files
  @@ -1138,7 +1219,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Preventing_modperl_process_from_">Preventing modperl process from going wild</A></H1></CENTER>
  +<CENTER><H1><A NAME="Preventing_mod_perl_Processes_Fr">Preventing mod_perl Processes From Going Wild</A></H1></CENTER>
   <P>
   Sometimes calling an undefined subroutine in a module can cause a tight
   loop that consumes all memory. Here is a way to catch such errors. Define
  @@ -1151,16 +1232,16 @@
     }
   </PRE>
   <P>
  -It will produce a nice error in error_log, giving the line number of the
  +This will produce a nice error in error_log, giving the line number of the
   call and the name of the undefined subroutine.
   
   <P>
   Sometimes an error happens and causes the server to write millions of lines
  -into your <CODE>error_log</CODE> file and in a few minutes to put your server down on its knees. For example
  -I get an error <CODE>Callback called
  -exit</CODE> show up in my error_log file many times. The <CODE>error_log</CODE> file grows to 300 Mbytes in size in a few minutes. You should run a cron
  -job to make sure this does not happen and if it does to take care of it.
  -Andreas J. Koenig is running this shell script every minute:
  +into your <EM>error_log</EM> file and in a few minutes to bring your server to its knees. For example
  +sometimes I get bursts of an error
  +<CODE>Callback called exit</CODE> showing up in my <EM>error_log</EM>. The file grows 300 Mbytes 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 runs this shell script every minute:
   
   <P>
   <PRE>  S=`ls -s /usr/local/apache/logs/error_log | awk '{print $1}'`
  @@ -1171,13 +1252,10 @@
     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.
  +On my server I run a watchdog every five minutes which restarts the server
  +if it gets stuck it always works since when some mod_perl child process
  +goes wild, the I/O it causes is so heavy that its sibling processes cannot
  +serve 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
  @@ -1186,11 +1264,11 @@
   
   <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.
  +  | 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>
  @@ -1226,7 +1304,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/05/2000
  +	     <BR>Last Modified at 02/26/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.5       +0 -0      modperl-site/guide/correct_headers.html
  
  Index: correct_headers.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/correct_headers.html,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- correct_headers.html	2000/02/09 21:11:39	1.4
  +++ correct_headers.html	2000/03/04 20:31:45	1.5
  @@ -229,7 +229,7 @@
     use Date::Parse;
     # Date::Parse parses RCS format, Apache::Util::parsedate doesn't
     $Mtime ||=
  -    Date::Parse::str2time(substr q$Date: 2000/02/09 21:11:39 $, 6);
  +    Date::Parse::str2time(substr q$Date: 2000/03/04 20:31:45 $, 6);
     $r-&gt;set_last_modified($Mtime);
   </PRE>
   <P>
  @@ -777,8 +777,8 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="VERSION">VERSION</A></H1></CENTER>
   <P>
  -You're reading revision $Revision: 1.4 $ of this document, written on
  -$Date: 2000/02/09 21:11:39 $
  +You're reading revision $Revision: 1.5 $ of this document, written on
  +$Date: 2000/03/04 20:31:45 $
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  
  
  
  1.12      +23 -759   modperl-site/guide/databases.html
  
  Index: databases.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/databases.html,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- databases.html	2000/02/09 21:11:39	1.11
  +++ databases.html	2000/03/04 20:31:45	1.12
  @@ -48,6 +48,7 @@
   	</UL>
   
   	<LI><A HREF="#mysql_use_result_vs_mysql_store">mysql_use_result vs. mysql_store_result.</A>
  +	<LI><A HREF="#Optimize_Run_Two_SQL_Engine_Ser">Optimize: Run Two SQL Engine Servers</A>
   	<LI><A HREF="#Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A>
   	<UL>
   
  @@ -423,6 +424,22 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Optimize_Run_Two_SQL_Engine_Ser">Optimize: Run Two SQL Engine Servers</A></H1></CENTER>
  +<P>
  +Sometimes you end up running many databases on the same machine. These
  +might have very varying database needs (such as one db with sessions, very
  +frequently updated but tiny amounts of data, and another with large sets of
  +data that's hardly ever updated) you might be able to gain a lot by running
  +two differently configured databases on one server. One would benefit from
  +lots of caching, the other would probably reduce the efficiency of the
  +cache but would gain from fast disk access. Different usage profiles
  +require vastly different performance needs.
  +
  +<P>
  +This is basically a similar idea to having <A HREF="././strategy.html#One_Plain_Apache_and_One_mod_per">two Apache servers</A>, each optimized for its specific requirements.
  +
  +<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
  @@ -453,767 +470,14 @@
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="The_My_DB_module">The My::DB module</A></H2></CENTER>
  -<P>
  +
  +	       <p><a href="code/My-DB.pm"><code>My-DB.pm</code></a> -- The My::DB module
  +
  +</p>
  +	      <P>
   (Note that you will not find this on CPAN. at least not yet :)
   
   <P>
  -<PRE>  package My::DB;
  -  
  -  use strict;
  -  use 5.004;
  -  
  -  use DBI;
  -  
  -  use vars qw(%c);
  -  use constant DEBUG =&gt; 0;
  -  
  -  %c =
  -    (
  -     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 takes care of caching 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 DEBUG;
  -  
  -      # init the sth - Statement handle object
  -    $self-&gt;{sth} = '';
  -  
  -    bless ($self, $class);
  -  
  -    $self;
  -  
  -  } # end of sub new
  -  
  -  
  -  
  -  ######################################################################
  -                 ###################################
  -                 ###                             ###
  -                 ###       SQL Functions         ###
  -                 ###                             ###
  -                 ###################################
  -  ######################################################################
  -  
  -  # print debug messages
  -  sub d{
  -     # we want to print the trace in debug mode
  -    print &quot;&lt;DT&gt;&lt;B&gt;&quot;.join(&quot;&lt;BR&gt;&quot;, @_).&quot;&lt;/B&gt;\n&quot; if DEBUG;
  -  
  -  } # end of sub d
  -  
  -  
  -  ######################################################################
  -  # return a count of matched rows, by conditions 
  -  #
  -  #  $count = sql_count_matched($table_name,\@conditions,\@restrictions);
  -  #
  -  # conditions must be an array so we can pass 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 are the list of restrictions like ('order by email')
  -  #
  -  ##########################
  -  sub sql_count_matched{
  -    my $self    = shift;
  -    my $table   = shift || '';
  -    my $r_conds = shift || [];
  -    my $r_restr = shift || [];
  -  
  -      # we want to print the trace in debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -      # 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;
  -  
  -      # restrictions (DONT put commas!)
  -    $do_sql .= &quot; &quot;. join &quot; &quot;, @{$r_restr} if @{$r_restr};
  -  
  -    d(&quot;SQL: $do_sql&quot;) if DEBUG;
  -  
  -      # 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;) if DEBUG;
  -  
  -    $self-&gt;{sth}-&gt;finish;
  -  
  -    return $count;
  -  
  -  } # end of sub sql_count_matched
  -  
  -  
  -  ######################################################################
  -  # return a count of matched distinct rows, by conditions 
  -  #
  -  #  $count = sql_count_matched_distinct($table_name,\@conditions,\@restrictions);
  -  #
  -  # 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 are the list of restrictions like ('order by email')
  -  #
  -  # This a slow implementation - because it cannot use select(*), but
  -  # brings all the records in first and then counts them. In the next
  -  # version of mysql there will be an operator 'select (distinct *)'
  -  # which will make things much faster, so we will just change the
  -  # internals of this sub, without changing the code itself.
  -  #
  -  ##############################
  -  sub sql_count_matched_distinct{
  -    my $self    = shift;
  -    my $table   = shift || '';
  -    my $r_conds = shift || [];
  -    my $r_restr = shift || [];
  -  
  -      # we want to print the trace in debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -      # build the query
  -    my $do_sql = &quot;SELECT DISTINCT * 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;) if DEBUG;
  -  
  -      # do query
  -  #  $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
  -  #  $self-&gt;{sth}-&gt;execute();
  -  
  -    my $count = @{$self-&gt;{dbh}-&gt;selectall_arrayref($do_sql)};
  -  
  -  #  my ($count) = $self-&gt;{sth}-&gt;fetchrow_array;
  -  
  -    d(&quot;Result: $count&quot;) if DEBUG;
  -  
  -  #  $self-&gt;{sth}-&gt;finish;
  -  
  -    return $count;
  -  
  -  } # end of sub sql_count_matched_distinct
  -  
  -  
  -  
  -  ######################################################################
  -  # 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 the trace debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -      # 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;) if DEBUG;
  -  
  -      # do query
  -    return $self-&gt;{dbh}-&gt;selectrow_array($do_sql);
  -  
  -  } # end of sub sql_get_matched_value
  -  
  -  
  -  
  -  
  -  ######################################################################
  -  # 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 none 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 || [];
  -  
  -      # we want to print in the trace debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -      # 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 @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;) if DEBUG;
  -  
  -      # do query
  -    @{$r_row} = $self-&gt;{dbh}-&gt;selectrow_array($do_sql);
  -  
  -  } # end of sub sql_get_matched_row
  -  
  -  
  -  
  -  ######################################################################
  -  # 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);
  -  #
  -  # 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_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 the trace debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -      # 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 @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;) if DEBUG;
  -  
  -      # do query
  -    $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
  -    $self-&gt;{sth}-&gt;execute();
  -  
  -    return $self-&gt;{sth}-&gt;fetchrow_hashref;
  -  
  -  } # end of sub sql_get_hash_ref
  -  
  -  
  -  
  -  
  -  
  -  ######################################################################
  -  # 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 || [];
  -  
  -      # we want to print in the trace debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -      # 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 @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
  -  
  -      # 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;) if DEBUG;
  -  
  -      # 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 the trace debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -      # 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;;
  -  
  -    d(&quot;SQL: $do_sql&quot;) if DEBUG;
  -  
  -      # 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
  -  #
  -  #  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' : '';
  -  
  -      # we want to print in the trace debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -      # 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;) if DEBUG;
  -  
  -      # 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;) if DEBUG;
  -  
  -  } # 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 the trace debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -      # build the query
  -    my $do_sql = &quot;DELETE 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]));
  -    }
  -  
  -      # Must be very careful 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;
  -  
  -    d(&quot;SQL: $do_sql&quot;) if DEBUG;
  -  
  -      # 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 the trace debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -    d(&quot;SQL: $do_sql&quot;) if DEBUG;
  -  
  -    $self-&gt;{dbh}-&gt;selectall_arrayref($do_sql);
  -  
  -  } # end of sub sql_execute_and_get_r_array
  -  
  -  
  -  ######################################################################
  -  # lock the passed tables in the requested mode (READ|WRITE) and set
  -  # internal flag to handle possible user abortions, so the tables will
  -  # be unlocked thru the END{} block
  -  #
  -  # sql_lock_tables('table1','lockmode',..,'tableN','lockmode'
  -  # lockmode = (READ | WRITE)
  -  #
  -  # _side_effect_ $self-&gt;{lock} = 'On';
  -  #
  -  ##########################
  -  sub sql_lock_tables{
  -    my $self   = shift;
  -    my %modes = @_;
  -  
  -    return unless %modes;
  -  
  -    my $do_sql = 'LOCK TABLES ';
  -    $do_sql .= join &quot;,&quot;, map {&quot;$_ $modes{$_}&quot;} keys %modes;
  -  
  -      # we want to print the trace in debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -    d(&quot;SQL: $do_sql&quot;) if DEBUG;
  -  
  -    $self-&gt;{sth} = $self-&gt;{dbh}-&gt;prepare($do_sql);
  -    $self-&gt;{sth}-&gt;execute();
  -  
  -      # Enough to set only one lock, unlock will remove them all
  -    $self-&gt;{lock} = 'On';
  -  
  -  } # end of sub sql_lock_tables
  -  
  -  
  -  
  -  ######################################################################
  -  # unlock all tables, unset internal flag to handle possible user
  -  # abortions, so the tables will be unlocked thru the END{} block
  -  #
  -  # sql_unlock_tables()
  -  #
  -  # _side_effect_: delete $self-&gt;{lock}
  -  #
  -  ##########################
  -  sub sql_unlock_tables{
  -    my $self   = shift;
  -  
  -      # we want to print the trace in debug mode
  -    d( &quot;[&quot;.(caller(2))[3].&quot; - &quot;.(caller(1))[3].&quot; - &quot;. (caller(0))[3].&quot;]&quot;) if DEBUG;
  -  
  -    $self-&gt;{dbh}-&gt;do(&quot;UNLOCK TABLES&quot;);
  -  
  -      # Enough to set only one lock, unlock will remove them all
  -    delete $self-&gt;{lock};
  -  
  -  } # end of sub sql_unlock_tables
  -  
  -  #
  -  #
  -  # return current date formatted for a DATE field type
  -  # YYYYMMDD
  -  #
  -  # Note: since this function actually doesn't need an object it's being
  -  # called without parameter as well as procedural call
  -  ############
  -  sub sql_date{
  -    my $self     = shift;
  -  
  -    my ($mday,$mon,$year) = (localtime)[3..5];
  -    return sprintf &quot;%0.4d%0.2d%0.2d&quot;,1900+$year,++$mon,$mday;
  -  
  -  } # end of sub sql_date
  -  
  -  #
  -  #
  -  # return current date formatted for a DATE field type
  -  # YYYYMMDDHHMMSS
  -  #
  -  # Note: since this function actually doesn't need an object it's being
  -  # called without parameter as well as procedural call
  -  ############
  -  sub sql_datetime{
  -    my $self     = shift;
  -  
  -    my ($sec,$min,$hour,$mday,$mon,$year) = localtime();
  -    return sprintf &quot;%0.4d%0.2d%0.2d%0.2d%0.2d%0.2d&quot;,1900+$year,++$mon,$mday,$hour,$min,$sec;
  -  
  -  } # end of sub sql_datetime
  -  
  -  
  -  # Quote the list of parameters.  Parameters consisting entirely of
  -  # digits (i.e. integers) are unquoted.
  -  # 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)
  -  # We make a copy of @_ since we might try to change the passed values,
  -  # producing an error when modification of a read-only value is 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;sql_unlock_tables() if $self-&gt;{lock};
  -    $self-&gt;{sth}-&gt;finish       if $self-&gt;{sth};
  -    $self-&gt;{dbh}-&gt;disconnect   if $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><H2><A NAME="My_DB_Module_s_Usage_Examples">My::DB Module's Usage Examples</A></H2></CENTER>
   <P>
  @@ -1419,7 +683,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/05/2000
  +	     <BR>Last Modified at 02/16/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.12      +10 -115   modperl-site/guide/dbm.html
  
  Index: dbm.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/dbm.html,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- dbm.html	2000/02/09 21:11:40	1.11
  +++ dbm.html	2000/03/04 20:31:45	1.12
  @@ -356,123 +356,18 @@
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="DB_File_Lock2">DB_File::Lock2</A></H1></CENTER>
  -<P>
  -Here is <CODE>DB_File::Lock2</CODE> which does the locking by using an external lockfile. This allows you to
  -gain the lock before the file is tied. Note that it's not yet on CPAN and
  -so is listed here in its entirety. Note also that this code still needs
  -some testing, so <STRONG>be
  +
  +	       <p><a href="code/DB_File-Lock2.pm"><code>DB_File-Lock2.pm</code></a> -- Here is C<DB_File::Lock2> which does the
  +locking by using an external lockfile.
  +
  +</p>
  +	      <P>
  +This allows you to gain the lock before the file is tied. Note that it's
  +not yet on CPAN and so is listed here in its entirety. Note also that this
  +code still needs some testing, so <STRONG>be
   careful</STRONG> if you use it on a production machine.
   
   <P>
  -<PRE>  package DB_File::Lock2;
  -  require 5.004;
  -  
  -  use strict;
  -  
  -  BEGIN {
  -      # RCS/CVS compliant:  must be all one line, for MakeMaker
  -    $DB_File::Lock2::VERSION = do { my @r = (q$Revision: 1.11 $ =~ /\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 Symbol ();
  -  
  -  @DB_File::Lock2::ISA    = qw( DB_File );
  -  %DB_File::Lock2::lockfhs = ();
  -  
  -  use constant DEBUG =&gt; 0;
  -  
  -    # file creation permissions mode
  -  use constant PERM_MODE =&gt; 0660;
  -  
  -    # file locking modes
  -  %DB_File::Lock2::locks =
  -    (
  -     read  =&gt; LOCK_SH,
  -     write =&gt; LOCK_EX,
  -    );
  -  
  -  # SYNOPSIS:
  -  # tie my %mydb, 'DB_File::Lock2', $filepath, 
  -  #     ['read' || 'write', 'HASH' || 'BTREE']
  -  # while (my($k,$v) = each %mydb) {
  -  #   print &quot;$k =&gt; $v\n&quot;;
  -  # }
  -  # untie %mydb;
  -  #########
  -  sub TIEHASH {
  -    my $class     = shift;
  -    my $file      = shift;
  -    my $lock_mode = lc shift || 'read';
  -    my $db_type   = shift || 'HASH';
  -  
  -    die &quot;Dunno about lock mode: [$lock_mode].\n
  -         Valid modes are 'read' or 'write'.\n&quot;
  -      unless $lock_mode eq 'read' or $lock_mode eq 'write';
  -  
  -    # Critical section starts here if in write mode!
  -  
  -      # create an external lock
  -    my $lockfh = Symbol::gensym();
  -    open $lockfh, &quot;&gt;$file.lock&quot; or die &quot;Cannot open $file.lock for writing: $!\n&quot;;
  -    unless (flock $lockfh, $DB_File::Lock2::locks{$lock_mode}) {
  -      croak &quot;cannot flock: $lock_mode =&gt; $DB_File::Lock2::locks{$lock_mode}: $!\n&quot;;
  -    }
  -  
  -    my $self = $class-&gt;SUPER::TIEHASH
  -      ($file,
  -       O_RDWR|O_CREAT,
  -       PERM_MODE,
  -       ($db_type eq 'BTREE' ? $DB_File::DB_BTREE : $DB_File::DB_HASH )
  -      );
  -  
  -      # remove the package name in case re-blessing occurs
  -    (my $id = &quot;$self&quot;) =~ s/^[^=]+=//;
  -  
  -      # cache the lock fh
  -    $DB_File::Lock2::lockfhs{$id} = $lockfh;
  -  
  -    return $self;
  -  
  -  } # end of sub new
  -  
  -  
  -  # DESTROY is automatically called when a tied variable
  -  # goes out of scope, on explicit untie() or when the program is
  -  # interrupted, e.g. with a die() call.
  -  # 
  -  # It unties the db by forwarding it to the parent class,
  -  # unlocks the file and removes it from the cache of locks.
  -  ###########
  -  sub DESTROY{
  -    my $self = shift;
  -  
  -    $self-&gt;SUPER::DESTROY(@_);
  -  
  -      # now it safe to unlock the file, (close() unlocks as well). Since
  -      # the object has gone we remove its lock filehandler entry
  -      # from the cache.
  -    (my $id = &quot;$self&quot;) =~ s/^[^=]+=//; # see 'sub TIEHASH'
  -    close delete $DB_File::Lock2::lockfhs{$id};
  -  
  -      # Critical section ends here if in write mode!
  -  
  -    print &quot;Destroying &quot;.__PACKAGE__.&quot;\n&quot; if DEBUG;
  -  
  -  }
  -  
  -  ####
  -  END {
  -    print &quot;Calling the END from &quot;.__PACKAGE__.&quot;\n&quot; if DEBUG;
  -  
  -  }
  -  
  -  1;
  -</PRE>
  -<P>
   And you use it like this:
   
   <P>
  @@ -575,7 +470,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/04/2000
  +	     <BR>Last Modified at 02/16/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.21      +17 -13    modperl-site/guide/debug.html
  
  Index: debug.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/debug.html,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- debug.html	2000/02/09 21:11:40	1.20
  +++ debug.html	2000/03/04 20:31:45	1.21
  @@ -830,12 +830,17 @@
   module. Both tools provide counters of processed requests per Apache
   process. So what you can do is to watch the report for about 5-10 minutes
   spotting which process number has the same number of processed requests
  -while its status is 'W' (Which means that it hangs), but when you have
  -about 50 processes, it's quite hard to spot such a process. So let's write
  -a watchdog to do the work for us:
  +while its status is 'W' (Which means that it hangs or ``runs away'')
   
   <P>
  -.....META??? Apache::SafeHang code
  +But when you have about 50 and more processes, it's quite hard to spot such
  +a process. So let's use a watchdog to do the work for us. I've put together
  +the
  +<A HREF="././modules.html#Apache_Watchdog_RunAway_Hang">Apache::Watchdog::RunAway</A>
  +module which includes the <CODE>amprapmon</CODE> utility whose name stands for
  +<EM>Apache mod_perl Run Away Processes Monitor</EM>. This utility monitors your server all the time and kills the processes
  +that serve a single request for too long. You define the threshold time for
  +the kill-off.
   
   <P>
   When you've got a real problem and the processes hang one after the other,
  @@ -1926,8 +1931,8 @@
     close $fh;
   </PRE>
   <P>
  -Now it's safe to unlock the dbm file. Please refer to <A HREF="././dbm.html#Locking_dbm_handlers">Locking dbm handlers</A> to learn why you should use a dbm's file descriptor to lock itself. To make
  -long explanations short -- it may get your dbm file corrupted.
  +Now it's safe to unlock the dbm file. Please refer to <A HREF="././dbm.html#Locking_dbm_handlers">Locking dbm handlers</A> to learn why you should NOT use a dbm's file descriptor to lock itself. To
  +make long explanations short -- it may get your dbm file corrupted.
   
   <P>
   <PRE>    # printout the contents of the the dbm file
  @@ -2774,9 +2779,6 @@
       $month++;
   </PRE>
   <P>
  -META: continue (unfinished)!!!
  -
  -<P>
   Now let's see some code including conditional and loop statements.
   
   <P>
  @@ -2785,6 +2787,9 @@
     }
   </PRE>
   <P>
  +META: continue (unfinished)!!!
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Using_print_and_Data_Dumper_f">Using print() and Data::Dumper for Debugging</A></H2></CENTER>
   <P>
  @@ -3656,9 +3661,8 @@
   
   <P>
   <PRE>  &lt;IfDefine PERLDB&gt;
  -</PRE>
  -<P>
  -<PRE>    &lt;Perl&gt;
  +  
  +    &lt;Perl&gt;
         use Apache::DB ();
         Apache::DB-&gt;init;
       &lt;/Perl&gt;
  @@ -4538,7 +4542,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/07/2000
  +	     <BR>Last Modified at 03/04/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.9       +36 -1     modperl-site/guide/download.html
  
  Index: download.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/download.html,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- download.html	2000/02/09 21:11:40	1.8
  +++ download.html	2000/03/04 20:31:45	1.9
  @@ -37,6 +37,7 @@
   	<LI><A HREF="#ab_ApacheBench">ab - ApacheBench</A>
   	<LI><A HREF="#High_Availability_Linux_Project">High-Availability Linux Project</A>
   	<LI><A HREF="#Apache_Request">Apache::Request</A>
  +	<LI><A HREF="#DataBases">DataBases</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -183,6 +184,27 @@
   
   
   <P>
  +Linux Virtual Server Project <A
  +HREF="http://www.linuxvirtualserver.org/">http://www.linuxvirtualserver.org/</A>
  +
  +
  +<P>
  +Efficient Support for P-HTTP in Cluster-Based Web Servers. (with Mohit Aron
  +and Willy Zwaenepoel.) In Proceedings of the USENIX 1999 Annual Technical
  +Conference, Monterey, CA, June 1999. <A
  +HREF="http://www.cs.rice.edu/~druschel/usenix99lard.ps.gz">http://www.cs.rice.edu/~druschel/usenix99lard.ps.gz</A>
  +<A
  +HREF="http://www.usenix.org/publications/library/proceedings/usenix99/full_papers/aron/aron_html/index.html">http://www.usenix.org/publications/library/proceedings/usenix99/full_papers/aron/aron_html/index.html</A>
  +
  +
  +<P>
  +The latest ip filter includes some simple load balancing code, that allows
  +a round-robin distribution onto several machines via ipnat. That may be a
  +simple solution for a few specific load problem. <A
  +HREF="http://coombs.anu.edu.au/~avalon/ipf3.4beta3.tgz">http://coombs.anu.edu.au/~avalon/ipf3.4beta3.tgz</A>
  +
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Apache_Request">Apache::Request</A></H1></CENTER>
   <P>
  @@ -190,6 +212,19 @@
   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="DataBases">DataBases</A></H1></CENTER>
  +<P>
  +Low-Cost Unix Database Differences <A
  +HREF="http://www.toodarkpark.org/computers/dbs.html">http://www.toodarkpark.org/computers/dbs.html</A>
  +
  +
  +<P>
  +My collection of various links to databases implementations <A
  +HREF="http://stason.org/TULARC/webmaster/db.html">http://stason.org/TULARC/webmaster/db.html</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>
  @@ -223,7 +258,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 01/17/2000
  +	     <BR>Last Modified at 03/03/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.21      +51 -18    modperl-site/guide/help.html
  
  Index: help.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/help.html,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- help.html	2000/02/09 21:11:44	1.20
  +++ help.html	2000/03/04 20:31:45	1.21
  @@ -89,7 +89,7 @@
   <P>
   However, you are welcome to submit corrections and suggestions directly to
   me at <A
  -HREF="mailto:sbekman@iname.com?subject=mod_perl%20guide%20corrections.">sbekman@iname.com?subject=mod_perl%20guide%20corrections.</A>
  +HREF="mailto:stas@stason.org?subject=mod_perl%20guide%20corrections.">stas@stason.org?subject=mod_perl%20guide%20corrections.</A>
   If you are going to <STRONG>submit heavy corrections of the text</STRONG> (I love those!), please help me by downloading the source pages in POD from
   the main (index) page (at the bottom) and directly editing them. I will use
   Emacs Ediff to perform an easy merge of your changes. Thank you!
  @@ -189,18 +189,20 @@
   HREF="http://www.perlreference.com/mod_perl/">http://www.perlreference.com/mod_perl/</A>
   
   
  -<P><LI><STRONG><A NAME="item_mod_perl">mod_perl mailing list</A></STRONG>
  +<P><LI><STRONG><A NAME="item_mod_perl">mod_perl mailing lists</A></STRONG>
  +<UL>
  +<P><LI><STRONG><A NAME="item_The">The mod_perl mailing list</A></STRONG>
   <P>
  -The Apache/Perl mailing list (<A
  -HREF="mailto:modperl@apache.org">modperl@apache.org</A>) <STRONG>is available for
  -mod_perl users and developers to share ideas, solve problems and
  -discuss things related to mod_perl and the Apache::* modules.</STRONG> To subscribe to this list, send mail to <A
  -HREF="mailto:majordomo@apache.org">majordomo@apache.org</A> with empty <CODE>Subject</CODE> and with <CODE>Body</CODE>:
  +The Apache/Perl mailing list <STRONG>is available for mod_perl users and
  +developers to share ideas, solve problems and discuss things related
  +to mod_perl and the Apache::* modules.</STRONG> To subscribe to this list, send email to <A
  +HREF="mailto:modperl-subscribe@apache.org">modperl-subscribe@apache.org</A>
  +. To unsubscribe send email to <A
  +HREF="mailto:modperl-unsubscribe@apache.org">modperl-unsubscribe@apache.org</A>
  +. Use <A HREF="mailto:modperl@apache.org">modperl@apache.org</A> adress to
  +post to the list.
   
   <P>
  -<PRE>  subscribe modperl
  -</PRE>
  -<P>
   A <STRONG>searchable</STRONG> mod_perl mailing list archive available at <A
   HREF="http://forum.swarthmore.edu/epigone/modperl">http://forum.swarthmore.edu/epigone/modperl</A>
   . We owe it to Ken Williams.
  @@ -218,12 +220,6 @@
   <P><LI>
   <P>
   <A
  -HREF="http://www.bitmechanic.com/mail-archives/modperl/">http://www.bitmechanic.com/mail-archives/modperl/</A>
  -
  -
  -<P><LI>
  -<P>
  -<A
   HREF="http://www.mail-archive.com/modperl%40apache.org/">http://www.mail-archive.com/modperl%40apache.org/</A>
   
   
  @@ -246,6 +242,43 @@
   
   
   </UL>
  +<P><LI><STRONG><A NAME="item_The">The advocacy mailing list</A></STRONG>
  +<P>
  +The advocacy list for mod_perl advocacy issues, discussions about site,
  +etc.
  +
  +<P>
  +Subscribe by sending a mail to <A
  +HREF="mailto:advocacy-subscribe@perl.apache.org.">advocacy-subscribe@perl.apache.org.</A>
  +Unsubscribe by sending a mail to <A
  +HREF="mailto:advocacy-unsubscribe@perl.apache.org.">advocacy-unsubscribe@perl.apache.org.</A>
  +Use <A HREF="mailto:advocacy@perl.apache.org">advocacy@perl.apache.org</A>
  +to post to the list.
  +
  +<P>
  +The archive: <A
  +HREF="http://www.mail-archive.com/advocacy@perl.apache.org/.">http://www.mail-archive.com/advocacy@perl.apache.org/.</A>
  +
  +
  +<P><LI><STRONG><A NAME="item_The">The modperl-cvs mailing list</A></STRONG>
  +<P>
  +The modperl developers list is the list where you can watch mod_perl
  +getting patched. No real discussions happen on this list, but if you want
  +to know about the latest changes in the mod_perl core before the rest of
  +the people, this is a list to be on.
  +
  +<P>
  +To subscribe to this list, send email to <A
  +HREF="mailto:modperl-cvs-subscribe@apache.org">modperl-cvs-subscribe@apache.org</A>
  +. To unsubscribe send email to <A
  +HREF="mailto:modperl-cvs-unsubscribe@apache.org">modperl-cvs-unsubscribe@apache.org</A>
  +. Use <A HREF="mailto:modperl-cvs@apache.org">modperl-cvs@apache.org</A>
  +adress to post to the list.
  +
  +<P>
  +No archives available.
  +
  +</UL>
   </UL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -286,7 +319,7 @@
   <P><LI><STRONG><A NAME="item_Answers">Answers to some bothering Perl and Perl/CGI questions</A></STRONG>
   <P>
   <A
  -HREF="http://www.singlesheaven.com/stas/TULARC/webmaster/myfaq.html">http://www.singlesheaven.com/stas/TULARC/webmaster/myfaq.html</A>
  +HREF="http://stason.org/TULARC/webmaster/myfaq.html">http://stason.org/TULARC/webmaster/myfaq.html</A>
   
   
   <P><LI><STRONG><A NAME="item_Idiot">Idiot's Guide to CGI programming</A></STRONG>
  @@ -439,7 +472,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/05/2000
  +	     <BR>Last Modified at 03/04/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.25      +99 -27    modperl-site/guide/index.html
  
  Index: index.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/index.html,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- index.html	2000/02/09 21:11:44	1.24
  +++ index.html	2000/03/04 20:31:45	1.25
  @@ -27,7 +27,7 @@
   <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.20 Feb, 9 2000</B></P></CENTER>
  +<CENTER><P><B>Version 1.21 Mar, 4 2000</B></P></CENTER>
    
   <P><HR WIDTH="100%"></P>
   
  @@ -197,6 +197,8 @@
   	<LI><A HREF="performance.html#Analysis_of_Software_and_Hardwar">Analysis of Software and Hardware Requirements</A>
   	<LI><A HREF="performance.html#Sharing_Memory">Sharing Memory</A>
   	<LI><A HREF="performance.html#How_Shared_Is_My_Memory_">How Shared Is My Memory?</A>
  +	<LI><A HREF="performance.html#Calculating_Real_Memory_Usage">Calculating Real Memory Usage</A>
  +	<LI><A HREF="performance.html#Is_my_Code_Shared_">Is my Code Shared?</A>
   	<LI><A HREF="performance.html#Preload_Perl_Modules_at_Server_S">Preload Perl Modules at Server Startup</A>
   	<UL>
   
  @@ -211,7 +213,7 @@
   	<LI><A HREF="performance.html#Caching_Components_with_HTML_Ma">Caching Components with HTML::Mason</A>
   	<LI><A HREF="performance.html#KeepAlive">KeepAlive</A>
   	<LI><A HREF="performance.html#Upload_Download_of_Big_Files">Upload/Download of Big Files</A>
  -	<LI><A HREF="performance.html#Forking_or_Executing_Subprocesse">Forking or Executing Subprocesses from mod_perl</A>
  +	<LI><A HREF="performance.html#Forking_and_Executing_Subprocess">Forking and Executing Subprocesses from mod_perl</A>
   	<LI><A HREF="performance.html#Memory_leakage">Memory leakage</A>
   	<UL>
   
  @@ -269,8 +271,18 @@
   	<LI><A HREF="performance.html#Using_1_Under_mod_perl_and_Be">Using $|=1 Under mod_perl and Better print() Techniques.</A>
   	<LI><A HREF="performance.html#More_Reducing_Memory_Usage_Tips">More Reducing Memory Usage Tips</A>
   	<LI><A HREF="performance.html#Measuring_the_Subroutines_Memory">Measuring the Subroutines Memory Usage</A>
  +	<LI><A HREF="performance.html#Memory_Swapping_is_Considered_Ba">Memory Swapping is Considered Bad</A>
   	<LI><A HREF="performance.html#Code_Profiling">Code Profiling</A>
  +	<LI><A HREF="performance.html#Reducing_the_Number_of_stat_Ca">Reducing the Number of stat() Calls</A>
   	<LI><A HREF="performance.html#Object_Methods_Calls_Versus_Func">Object Methods Calls Versus Function Calls</A>
  +	<UL>
  +
  +		<LI><A HREF="performance.html#The_Overhead_with_Light_Subrouti">The Overhead with Light Subroutines</A>
  +		<LI><A HREF="performance.html#The_Overhead_with_Heavy_Subrouti">The Overhead with Heavy Subroutines</A>
  +		<LI><A HREF="performance.html#Are_All_Methods_Slower_than_Func">Are All Methods Slower than Functions?</A>
  +	</UL>
  +
  +	<LI><A HREF="performance.html#Imported_Symbols_and_Memory_Usag">Imported Symbols and Memory Usage</A>
   	<LI><A HREF="performance.html#Sending_Plain_HTML_as_Compressed">Sending Plain HTML as Compressed Output</A>
   	<LI><A HREF="performance.html#Increasing_Shared_Memory_With_me">Increasing Shared Memory With mergemem</A>
   </UL>
  @@ -302,13 +314,13 @@
   
   			<LI><A HREF="install.html#Reusing_Configuration_Parameters">Reusing Configuration Parameters</A>
   			<LI><A HREF="install.html#Discovering_whether_some_option_">Discovering whether some option was configured</A>
  -			<LI><A HREF="install.html#Using_an_alternative_Configurati">Using an alternative Configuration file</A>
  +			<LI><A HREF="install.html#Using_an_Alternative_Configurati">Using an Alternative Configuration File</A>
   			<LI><A HREF="install.html#perl_Makefile_PL_Troubleshooting">perl Makefile.PL Troubleshooting</A>
   			<UL>
   
   				<LI><A HREF="install.html#_A_test_compilation_with_your_Ma">&quot;A test compilation with your Makefile configuration failed...&quot;</A>
   				<LI><A HREF="install.html#Missing_or_Misconfigured_libgdbm">Missing or Misconfigured libgdbm.so</A>
  -				<LI><A HREF="install.html#undefined_reference_to_PL_perl_">undefined reference to `PL_perl_destruct_level'</A>
  +				<LI><A HREF="install.html#Undefined_reference_to_PL_perl_">Undefined reference to `PL_perl_destruct_level'</A>
   			</UL>
   
   		</UL>
  @@ -319,8 +331,8 @@
   			<LI><A HREF="install.html#make_Troubleshooting">make Troubleshooting</A>
   			<UL>
   
  -				<LI><A HREF="install.html#undefined_reference_to_Perl_new">undefined reference to 'Perl_newAV'</A>
  -				<LI><A HREF="install.html#unrecognized_format_specifier_fo">unrecognized format specifier for...</A>
  +				<LI><A HREF="install.html#Undefined_reference_to_Perl_new">Undefined reference to 'Perl_newAV'</A>
  +				<LI><A HREF="install.html#Unrecognized_format_specifier_fo">Unrecognized format specifier for...</A>
   			</UL>
   
   		</UL>
  @@ -333,9 +345,9 @@
   			<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#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of Apache</A>
   				<LI><A HREF="install.html#make_test_skipping_test_on_">make test......skipping test on this platform</A>
  -				<LI><A HREF="install.html#make_test_fails_due_to_misconfig">make test fails due to misconfigured localhost</A>
  +				<LI><A HREF="install.html#make_test_Fails_Due_to_Misconfig">make test Fails Due to Misconfigured localhost Entry</A>
   			</UL>
   
   		</UL>
  @@ -349,8 +361,13 @@
   
   		<LI><A HREF="install.html#The_All_In_One_Way">The All-In-One Way</A>
   		<LI><A HREF="install.html#The_Flexible_Way">The Flexible Way</A>
  -		<LI><A HREF="install.html#Build_mod_perl_as_DSO_inside_Apa">Build mod_perl as DSO inside Apache source tree via APACI</A>
  -		<LI><A HREF="install.html#Build_mod_perl_as_DSO_outside_Ap">Build mod_perl as DSO outside Apache source tree via APXS</A>
  +		<LI><A HREF="install.html#Build_mod_perl_as_a_DSO_inside_t">Build mod_perl as a DSO inside the Apache Source Tree via APACI</A>
  +		<UL>
  +
  +			<LI><A HREF="install.html#libperl_so_and_libperl_a">libperl.so and libperl.a</A>
  +		</UL>
  +
  +		<LI><A HREF="install.html#Build_mod_perl_as_a_DSO_outside_">Build mod_perl as a DSO outside the Apache Source Tree via APXS</A>
   	</UL>
   
   	<LI><A HREF="install.html#Installation_Scenarios_for_mod_p">Installation Scenarios for mod_perl and Other Components</A>
  @@ -367,7 +384,7 @@
   
   	</UL>
   
  -	<LI><A HREF="install.html#mod_perl_Installation_with_CPAN_">mod_perl Installation with CPAN.pm's Interactive Shell</A>
  +	<LI><A HREF="install.html#mod_perl_Installation_with_the_C">mod_perl Installation with the CPAN.pm Interactive Shell</A>
   	<LI><A HREF="install.html#Installing_on_multiple_machines">Installing on multiple machines</A>
   	<LI><A HREF="install.html#using_RPM_DEB_and_other_package">using RPM, DEB and other packages to install mod_perl</A>
   	<UL>
  @@ -388,17 +405,22 @@
   
   		<LI><A HREF="install.html#Installing_Perl_Modules_into_a_D">Installing Perl Modules into a Directory of Choice</A>
   		<LI><A HREF="install.html#Making_Your_Scripts_Find_the_Loc">Making Your Scripts Find the Locally Installed Modules</A>
  -		<LI><A HREF="install.html#CPAN_pm_Shell_and_Locally_Instal">CPAN.pm Shell and Locally Installed Modules</A>
  +		<LI><A HREF="install.html#The_CPAN_pm_Shell_and_Locally_In">The CPAN.pm Shell and Locally Installed Modules</A>
   		<LI><A HREF="install.html#Making_a_Local_Apache_Installati">Making a Local Apache Installation</A>
  -		<LI><A HREF="install.html#Actual_Local_mod_perl_Enabled_Ap">Actual Local mod_perl Enabled Apache Installation</A>
  +		<LI><A HREF="install.html#Local_mod_perl_Enabled_Apache_In">Local mod_perl Enabled Apache Installation</A>
  +		<UL>
  +
  +			<LI><A HREF="install.html#Resource_Usage">Resource Usage</A>
  +		</UL>
  +
   		<LI><A HREF="install.html#Local_mod_perl_Enabled_Apache_In">Local mod_perl Enabled Apache Installation with CPAN.pm</A>
   	</UL>
   
   	<LI><A HREF="install.html#Automating_installation">Automating installation</A>
  -	<LI><A HREF="install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A>
  +	<LI><A HREF="install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running?</A>
   	<UL>
   
  -		<LI><A HREF="install.html#Testing_by_checking_the_error_lo">Testing by checking the error_log file</A>
  +		<LI><A HREF="install.html#Checking_the_error_log">Checking the error_log</A>
   		<LI><A HREF="install.html#Testing_by_viewing_perl_status">Testing by viewing /perl-status</A>
   		<LI><A HREF="install.html#Testing_via_telnet">Testing via telnet</A>
   		<LI><A HREF="install.html#Testing_via_a_CGI_script">Testing via a CGI script</A>
  @@ -408,10 +430,10 @@
   	<LI><A HREF="install.html#General_Notes">General Notes</A>
   	<UL>
   
  -		<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>
  +		<LI><A HREF="install.html#Should_I_Rebuild_mod_perl_if_I_h">Should I Rebuild mod_perl if I have Upgraded Perl?</A>
   		<LI><A HREF="install.html#Perl_installation_requirements">Perl installation requirements</A>
   		<LI><A HREF="install.html#mod_auth_dbm_nuances">mod_auth_dbm nuances</A>
  -		<LI><A HREF="install.html#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
  +		<LI><A HREF="install.html#Stripping_Apache_to_make_it_almo">Stripping Apache to make it almost a Perl-server</A>
   		<LI><A HREF="install.html#Saving_the_config_status_Files_w">Saving the config.status Files with mod_perl, php, ssl and Other Components</A>
   		<LI><A HREF="install.html#What_Compiler_Should_Be_Used_to_">What Compiler Should Be Used to Build mod_perl?</A>
   	</UL>
  @@ -468,6 +490,7 @@
   	</UL>
   
   	<LI><A HREF="config.html#Validating_the_Configuration_Syn">Validating the Configuration Syntax</A>
  +	<LI><A HREF="config.html#Enabling_Remote_Server_Configura">Enabling Remote Server Configuration Reports</A>
   	<LI><A HREF="config.html#Publishing_Port_Numbers_Differen">Publishing Port Numbers Different from 80</A>
   	<LI><A HREF="config.html#Configuring_Apache_mod_perl_wi">Configuring Apache + mod_perl with mod_macro</A>
   	<LI><A HREF="config.html#General_Pitfalls">General Pitfalls</A>
  @@ -507,6 +530,21 @@
   		<LI><A HREF="strategy.html#Apache_s_mod_proxy">Apache's mod_proxy</A>
   	</UL>
   
  +	<LI><A HREF="strategy.html#When_One_Machine_is_not_Enough_f">When One Machine is not Enough for SQL DB and mod_perl</A>
  +	<UL>
  +
  +		<LI><A HREF="strategy.html#Servers_Requirements">Servers' Requirements</A>
  +		<LI><A HREF="strategy.html#The_Problem">The Problem</A>
  +		<LI><A HREF="strategy.html#The_Solution">The Solution</A>
  +		<UL>
  +
  +			<LI><A HREF="strategy.html#Pros">Pros</A>
  +			<LI><A HREF="strategy.html#Cons">Cons</A>
  +		</UL>
  +
  +		<LI><A HREF="strategy.html#Three_Machines_Model">Three Machines Model</A>
  +	</UL>
  +
   </UL>
   <P>
   <LI><A HREF="scenario.html"><B><FONT SIZE=+1>Real World Scenarios</FONT></B></A></LI><P>
  @@ -547,9 +585,37 @@
   		<LI><A HREF="scenario.html#Installation_and_Configuration">Installation and Configuration</A>
   		<LI><A HREF="scenario.html#Tricks_Traps_and_Gotchas">Tricks, Traps and Gotchas</A>
   	</UL>
  +
  +	<LI><A HREF="scenario.html#mod_proxy">mod_proxy</A>
  +	<UL>
  +
  +		<LI><A HREF="scenario.html#Concepts_and_Configuration_Direc">Concepts and Configuration Directives</A>
  +		<UL>
  +
  +			<LI><A HREF="scenario.html#ProxyPass">ProxyPass</A>
  +			<LI><A HREF="scenario.html#ProxyPassReverse">ProxyPassReverse</A>
  +		</UL>
  +
  +		<LI><A HREF="scenario.html#Buffering_Feature">Buffering Feature</A>
  +		<UL>
  +
  +			<LI><A HREF="scenario.html#Setting_the_Buffering_Limits_on_">Setting the Buffering Limits on Various OSes</A>
  +			<UL>
  +
  +				<LI><A HREF="scenario.html#IOBUFSIZE_Source_Code_Definition">IOBUFSIZE Source Code Definition</A>
  +				<LI><A HREF="scenario.html#ProxyReceiveBufferSize_Configura">ProxyReceiveBufferSize Configuration Directive</A>
  +				<LI><A HREF="scenario.html#Hacking_the_Code">Hacking the Code</A>
  +			</UL>
  +
  +		</UL>
  +
  +		<LI><A HREF="scenario.html#Caching">Caching</A>
  +		<LI><A HREF="scenario.html#Building_process">Building process</A>
  +	</UL>
   
  -	<LI><A HREF="scenario.html#Building_and_Using_mod_proxy">Building and Using mod_proxy</A>
  +	<LI><A HREF="scenario.html#mod_proxy_add_forward_and_X_Forw">mod_proxy_add_forward and X-Forwarded-For header</A>
   	<LI><A HREF="scenario.html#HTTP_Authentication_With_Two_Ser">HTTP Authentication With Two Servers Plus a Proxy</A>
  +	<LI><A HREF="scenario.html#mod_rewrite_Examples">mod_rewrite Examples</A>
   </UL>
   <P>
   <LI><A HREF="frequent.html"><B><FONT SIZE=+1>Frequent mod_perl problems</FONT></B></A></LI><P>
  @@ -569,14 +635,14 @@
   	<LI><A HREF="control.html#Using_apachectl_to_control_the_s">Using apachectl to control the server</A>
   	<LI><A HREF="control.html#Safe_Code_Updates_on_a_Live_Prod">Safe Code Updates on a Live Production Server</A>
   	<LI><A HREF="control.html#An_Intentional_Disabling_of_Live">An Intentional Disabling of Live Scripts</A>
  -	<LI><A HREF="control.html#SUID_start_up_scripts">SUID start-up scripts</A>
  +	<LI><A HREF="control.html#SUID_Start_up_Scripts">SUID Start-up Scripts</A>
   	<LI><A HREF="control.html#Preparing_for_Machine_Reboot">Preparing for Machine Reboot</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#Monitoring_the_Server_A_watchdo">Monitoring the Server.  A watchdog.</A>
  +	<LI><A HREF="control.html#Running_a_Server_in_Single_Proce">Running a Server in Single Process 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_modperl_process_from_">Preventing modperl process from going wild</A>
  +	<LI><A HREF="control.html#Preventing_mod_perl_Processes_Fr">Preventing mod_perl Processes From Going Wild</A>
   </UL>
   <P>
   <LI><A HREF="obvious.html"><B><FONT SIZE=+1>Things obvious to others, but not to you</FONT></B></A></LI><P>
  @@ -736,6 +802,7 @@
   	</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#Optimize_Run_Two_SQL_Engine_Ser">Optimize: Run Two SQL Engine Servers</A>
   	<LI><A HREF="databases.html#Some_useful_code_snippets_to_be_">Some useful code snippets to be used with relational Databases</A>
   	<UL>
   
  @@ -869,6 +936,9 @@
   
   	<LI><A HREF="modules.html#Apache_Session_Maintain_sessi">Apache::Session - Maintain session state across HTTP requests</A>
   	<LI><A HREF="modules.html#Apache_DBI_Initiate_a_persist">Apache::DBI - Initiate a persistent database connection</A>
  +	<LI><A HREF="modules.html#Apache_Watchdog_RunAway_Hang">Apache::Watchdog::RunAway - Hanging Processes Monitor and Terminator</A>
  +	<LI><A HREF="modules.html#Apache_VMonitor_Visual_System">Apache::VMonitor - Visual System and Apache Server Monitor</A>
  +	<LI><A HREF="modules.html#Apache_GTopLimit_Limit_Apache">Apache::GTopLimit - Limit Apache httpd processes</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_RegistryNG_Apache_Re">Apache::RegistryNG -- Apache::Registry New Generation</A>
  @@ -906,6 +976,7 @@
   	<LI><A HREF="snippets.html#A_Simple_Handler_To_Print_The_En">A Simple Handler To Print The Environment Variables</A>
   	<LI><A HREF="snippets.html#mod_rewrite_Based_On_Query_Strin">mod_rewrite Based On Query String and URI Implemented in Perl</A>
   	<LI><A HREF="snippets.html#Setting_PerlHandler_Based_on_MIM">Setting PerlHandler Based on MIME Type</A>
  +	<LI><A HREF="snippets.html#Using_DESTROY_to_Finalize_Output">Using DESTROY to Finalize Output</A>
   	<LI><A HREF="snippets.html#Mysql_Backup_and_Restore_Scripts">Mysql Backup and Restore Scripts</A>
   </UL>
   <P>
  @@ -974,6 +1045,7 @@
   	<LI><A HREF="download.html#ab_ApacheBench">ab - ApacheBench</A>
   	<LI><A HREF="download.html#High_Availability_Linux_Project">High-Availability Linux Project</A>
   	<LI><A HREF="download.html#Apache_Request">Apache::Request</A>
  +	<LI><A HREF="download.html#DataBases">DataBases</A>
   </UL>
   <P>
   
  @@ -995,13 +1067,13 @@
   	    All the HTML files, POD sources and build scripts are
   	    available from <A
   	    HREF="http://www.perl.com/CPAN-local/authors/id/S/ST/STAS/">
  -	    my directory at CPAN</A>.
  +	    my directory at CPAN or its mirrors</A>.
   	  </LI>
   
   	  <LI> 
   	    Here is the <A HREF="mod_perl_guide.pdf.gz"> Book-like
   	    version </A> (PDF format). Note that <CODE>gv</CODE>
  -	    (<CODE>ghostviewer</CODE>) in addition to viewing PS
  +	    (<CODE>ghostview</CODE>) in addition to viewing PS
   	    files, knows to handle PDF files as well. Use
   	    <CODE>pdf2ps</CODE> utility to convert PDF to PS format if
   	    wanted to.
  @@ -1083,7 +1155,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 02/09/2000
  +HREF="help.html#This_document_s_Author">Stas Bekman</A>.<BR> Last Modified at 03/04/2000
   </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.12      +908 -818  modperl-site/guide/install.html
  
  Index: install.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/install.html,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- install.html	2000/02/09 21:11:44	1.11
  +++ install.html	2000/03/04 20:31:45	1.12
  @@ -50,13 +50,13 @@
   
   			<LI><A HREF="#Reusing_Configuration_Parameters">Reusing Configuration Parameters</A>
   			<LI><A HREF="#Discovering_whether_some_option_">Discovering whether some option was configured</A>
  -			<LI><A HREF="#Using_an_alternative_Configurati">Using an alternative Configuration file</A>
  +			<LI><A HREF="#Using_an_Alternative_Configurati">Using an Alternative Configuration File</A>
   			<LI><A HREF="#perl_Makefile_PL_Troubleshooting">perl Makefile.PL Troubleshooting</A>
   			<UL>
   
   				<LI><A HREF="#_A_test_compilation_with_your_Ma">&quot;A test compilation with your Makefile configuration failed...&quot;</A>
   				<LI><A HREF="#Missing_or_Misconfigured_libgdbm">Missing or Misconfigured libgdbm.so</A>
  -				<LI><A HREF="#undefined_reference_to_PL_perl_">undefined reference to `PL_perl_destruct_level'</A>
  +				<LI><A HREF="#Undefined_reference_to_PL_perl_">Undefined reference to `PL_perl_destruct_level'</A>
   			</UL>
   
   		</UL>
  @@ -67,8 +67,8 @@
   			<LI><A HREF="#make_Troubleshooting">make Troubleshooting</A>
   			<UL>
   
  -				<LI><A HREF="#undefined_reference_to_Perl_new">undefined reference to 'Perl_newAV'</A>
  -				<LI><A HREF="#unrecognized_format_specifier_fo">unrecognized format specifier for...</A>
  +				<LI><A HREF="#Undefined_reference_to_Perl_new">Undefined reference to 'Perl_newAV'</A>
  +				<LI><A HREF="#Unrecognized_format_specifier_fo">Unrecognized format specifier for...</A>
   			</UL>
   
   		</UL>
  @@ -81,9 +81,9 @@
   			<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="#mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of Apache</A>
   				<LI><A HREF="#make_test_skipping_test_on_">make test......skipping test on this platform</A>
  -				<LI><A HREF="#make_test_fails_due_to_misconfig">make test fails due to misconfigured localhost</A>
  +				<LI><A HREF="#make_test_Fails_Due_to_Misconfig">make test Fails Due to Misconfigured localhost Entry</A>
   			</UL>
   
   		</UL>
  @@ -97,8 +97,13 @@
   
   		<LI><A HREF="#The_All_In_One_Way">The All-In-One Way</A>
   		<LI><A HREF="#The_Flexible_Way">The Flexible Way</A>
  -		<LI><A HREF="#Build_mod_perl_as_DSO_inside_Apa">Build mod_perl as DSO inside Apache source tree via APACI</A>
  -		<LI><A HREF="#Build_mod_perl_as_DSO_outside_Ap">Build mod_perl as DSO outside Apache source tree via APXS</A>
  +		<LI><A HREF="#Build_mod_perl_as_a_DSO_inside_t">Build mod_perl as a DSO inside the Apache Source Tree via APACI</A>
  +		<UL>
  +
  +			<LI><A HREF="#libperl_so_and_libperl_a">libperl.so and libperl.a</A>
  +		</UL>
  +
  +		<LI><A HREF="#Build_mod_perl_as_a_DSO_outside_">Build mod_perl as a DSO outside the Apache Source Tree via APXS</A>
   	</UL>
   
   	<LI><A HREF="#Installation_Scenarios_for_mod_p">Installation Scenarios for mod_perl and Other Components</A>
  @@ -115,7 +120,7 @@
   
   	</UL>
   
  -	<LI><A HREF="#mod_perl_Installation_with_CPAN_">mod_perl Installation with CPAN.pm's Interactive Shell</A>
  +	<LI><A HREF="#mod_perl_Installation_with_the_C">mod_perl Installation with the CPAN.pm Interactive Shell</A>
   	<LI><A HREF="#Installing_on_multiple_machines">Installing on multiple machines</A>
   	<LI><A HREF="#using_RPM_DEB_and_other_package">using RPM, DEB and other packages to install mod_perl</A>
   	<UL>
  @@ -136,17 +141,22 @@
   
   		<LI><A HREF="#Installing_Perl_Modules_into_a_D">Installing Perl Modules into a Directory of Choice</A>
   		<LI><A HREF="#Making_Your_Scripts_Find_the_Loc">Making Your Scripts Find the Locally Installed Modules</A>
  -		<LI><A HREF="#CPAN_pm_Shell_and_Locally_Instal">CPAN.pm Shell and Locally Installed Modules</A>
  +		<LI><A HREF="#The_CPAN_pm_Shell_and_Locally_In">The CPAN.pm Shell and Locally Installed Modules</A>
   		<LI><A HREF="#Making_a_Local_Apache_Installati">Making a Local Apache Installation</A>
  -		<LI><A HREF="#Actual_Local_mod_perl_Enabled_Ap">Actual Local mod_perl Enabled Apache Installation</A>
  +		<LI><A HREF="#Local_mod_perl_Enabled_Apache_In">Local mod_perl Enabled Apache Installation</A>
  +		<UL>
  +
  +			<LI><A HREF="#Resource_Usage">Resource Usage</A>
  +		</UL>
  +
   		<LI><A HREF="#Local_mod_perl_Enabled_Apache_In">Local mod_perl Enabled Apache Installation with CPAN.pm</A>
   	</UL>
   
   	<LI><A HREF="#Automating_installation">Automating installation</A>
  -	<LI><A HREF="#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A>
  +	<LI><A HREF="#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running?</A>
   	<UL>
   
  -		<LI><A HREF="#Testing_by_checking_the_error_lo">Testing by checking the error_log file</A>
  +		<LI><A HREF="#Checking_the_error_log">Checking the error_log</A>
   		<LI><A HREF="#Testing_by_viewing_perl_status">Testing by viewing /perl-status</A>
   		<LI><A HREF="#Testing_via_telnet">Testing via telnet</A>
   		<LI><A HREF="#Testing_via_a_CGI_script">Testing via a CGI script</A>
  @@ -156,10 +166,10 @@
   	<LI><A HREF="#General_Notes">General Notes</A>
   	<UL>
   
  -		<LI><A HREF="#Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A>
  +		<LI><A HREF="#Should_I_Rebuild_mod_perl_if_I_h">Should I Rebuild mod_perl if I have Upgraded Perl?</A>
   		<LI><A HREF="#Perl_installation_requirements">Perl installation requirements</A>
   		<LI><A HREF="#mod_auth_dbm_nuances">mod_auth_dbm nuances</A>
  -		<LI><A HREF="#Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A>
  +		<LI><A HREF="#Stripping_Apache_to_make_it_almo">Stripping Apache to make it almost a Perl-server</A>
   		<LI><A HREF="#Saving_the_config_status_Files_w">Saving the config.status Files with mod_perl, php, ssl and Other Components</A>
   		<LI><A HREF="#What_Compiler_Should_Be_Used_to_">What Compiler Should Be Used to Build mod_perl?</A>
   	</UL>
  @@ -194,15 +204,15 @@
   <CENTER><H1><A NAME="Installing_mod_perl_in_10_Minute">Installing mod_perl in 10 Minutes and 10 Command Lines</A></H1></CENTER>
   <P>
   Did you know that it takes about 10 minutes to build and install mod_perl
  -enabled Apache on a pretty average processor and decent amount of system
  -memory? It goes like that:
  +enabled Apache on a pretty average processor with a decent amount of system
  +memory? It goes like this:
   
   <P>
   <PRE>  % cd /usr/src
     % lwp-download <A HREF="http://www.apache.org/dist/apache_x.x.x.tar.gz">http://www.apache.org/dist/apache_x.x.x.tar.gz</A>
     % lwp-download <A HREF="http://perl.apache.org/dist/mod_perl-x.xx.tar.gz">http://perl.apache.org/dist/mod_perl-x.xx.tar.gz</A>
  -  % tar zvxf apache_x.x.x.tar.gz
  -  % tar zvxf mod_perl-x.xx.tar.gz
  +  % tar xzvf apache_x.x.x.tar.gz
  +  % tar xzvf mod_perl-x.xx.tar.gz
     % cd mod_perl-x.xx
     % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
       DO_HTTPD=1 USE_APACI=1 EVERYTHING=1
  @@ -214,50 +224,56 @@
   That's all!
   
   <P>
  -* Of course replace <EM>x.x.x</EM> with the real version numbers of mod_perl and Apache.
  +* Of course you should replace <EM>x.xx</EM> and <EM>x.x.x</EM> with the real version numbers of mod_perl and Apache.
   
   <P>
  -* GNU <CODE>tar</CODE> utility knows to uncompress as well (with <CODE>z</CODE> flag).
  +* The GNU <CODE>tar</CODE> utility knows how to uncompress (the <CODE>z</CODE> flag).
   
   <P>
  -What's left is to add a few configuration lines to a <CODE>httpd.conf</CODE>, an Apache configuration file, start the server and enjoy mod_perl.
  +All that's left is to add a few configuration lines to <CODE>httpd.conf</CODE>, the Apache configuration file, start the server and enjoy mod_perl.
   
   <P>
   If you have stumbled upon a problem at any of the above steps, don't
  -despair -- the next section will explain in details each and every step.
  +despair, the next sections will explain in detail each and every step.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="The_Gory_Details">The Gory Details</A></H1></CENTER>
   <P>
   We saw that the basic mod_perl installation is quite simple and takes about
  -10 command that can be copied and pasted from these pages. However,
  -sometimes you need to make different optimizations by passing only specific
  -parameters (compared to <CODE>EVERYTHING=1</CODE>), bundling other components with mod_perl and etc. You may want to build
  -mod_perl as loadable object, that can be upgraded without rebuilding the
  +10 commands. You can copy and paste them from these pages. The parameter <CODE>EVERYTHING=1</CODE> selects a lot of options, but sometimes you will need different ones. You
  +may need to pass only specific parameters, to bundle other components with
  +mod_perl etc. You may want to build mod_perl as loadable object instead of
  +compiling it into Apache, so that it can be upgraded without rebuilding
   Apache itself.
   
   <P>
   To accomplish this you will want to understand various techniques for
   mod_perl configuration and building. You need to know what configuration
  -parameters are available and when each of them should be used.
  +parameters are available to you and when to use them.
   
   <P>
  -Like with Perl, simple things are simple with mod_perl, but when you need
  -to accomplish some more complicated tasks you have to invest some time into
  -a deeper understanding of the process. In this chapter we will take the
  +As with Perl, with mod_perl simple things are simple. But when you need to
  +accomplish more complicated tasks you may have to invest some time to gain
  +a deeper understanding of the process. In this chapter I will take the
   following route. I'll start with a detailed explanation of the four stages
  -of the mod_perl installation process, then continue with different passes
  -each installation might take according to your goal, following by a few
  -copy-and-paste real world installation scenarios. Toward the end of the
  -chapter we will see various approaches that make the installations easier,
  -by automating most of the process' steps , finally I'll cover some of the
  -general issues users get stumbled with while installing mod_perl.
  +of the mod_perl installation process, then continue with the different
  +paths each installation might take according to your goal, followed by a
  +few copy-and-paste real world installation scenarios. Towards the end of
  +the chapter I will show you various approaches that make the installations
  +easier, automating most of the steps. Finally I'll cover some of the
  +general issues that can cause new users to stumble while installing
  +mod_perl.
   
   <P>
   We can clearly separate the installation process into the following stages:
  -Sources Configuration, Building, Testing and Installation itself.
   
  +<UL>
  +<P><LI><STRONG><A NAME="item_Sources">Sources Configuration,</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Building">Building,</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Testing">Testing and</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Installation">Installation.</A></STRONG>
  +</UL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Sources_Configuration_perl_Make">Sources Configuration (perl Makefile.PL ...)</A></H2></CENTER>
  @@ -273,21 +289,20 @@
   accept and explain each one of them.
   
   <P>
  -But first let's see what configuration mechanisms we have in our hands.
  -Basically from the configuration point, all of them define a special set of
  -parameters to be passed to <CODE>perl
  -Makefile.PL</CODE>. Depending on the chosen configuration, the final product might be a
  -stand-alone http binary, a loadable object or else.
  +First let's see what configuration mechanisms we have available. Basically
  +they all define a special set of parameters to be passed to
  +<CODE>perl Makefile.PL</CODE>. Depending on the chosen configuration, the final product might be a
  +stand-alone httpd binary or a loadable object.
   
   <P>
   The source configuration mechanism in Apache 1.3 provides four major
  -highlights mod_perl can benefit from:
  +features from which mod_perl can benefit:
   
   <DL>
   <P><DT><STRONG><A NAME="item_Per">Per-module configuration scripts (ConfigStart/End)</A></STRONG><DD>
   <P>
   This is a mechanism modules can use to link themselves into the
  -configuration processing. It is useful for automatically adjusting
  +configuration process. It is useful for automatically adjusting
   configuration and build parameters from the modules sources. It is
   triggered by <CODE>ConfigStart</CODE>/<CODE>ConfigEnd</CODE> sections inside
   <EM>modulename</EM><CODE>.module</CODE> files.
  @@ -296,62 +311,60 @@
   <P>
   This is the new top-level <CODE>configure</CODE> script from Apache 1.3 which provides a GNU Autoconf-style interface. It is
   useful for configuring the source tree without manually editing any <CODE>src/Configuration</CODE>
  -files. Any parameterization can be done via command line options to the
  -<CODE>configure</CODE> script. Internally this is just a nifty a wrapper to the old <CODE>src/Configure</CODE> script.
  +files. Any parameterization can be done via command line options to the <CODE>configure</CODE> script. Internally this is just a nifty wrapper to the old <CODE>src/Configure</CODE> script.
   
   <P>
  -Since Apache 1.3 this is a De facto way to install mod_perl as clean as
  -possible. This currently is a pure Unix-based solution because the complete
  -Apache 1.3 source configuration mechanism currently is only workable under
  -Unix. It doesn't work under the Win32 platform, so mod_perl cannot use it
  -there, too.
  +Since Apache 1.3 this is the way to install mod_perl as cleanly as
  +possible. Currently this is a pure Unix-based solution because at present
  +the complete Apache 1.3 source configuration mechanism is only available
  +under Unix. It doesn't work on the Win32 platform.
   
   <P><DT><STRONG><A NAME="item_Dynamic">Dynamic Shared Object (DSO) support</A></STRONG><DD>
   <P>
   This is beside Windows NT support one of most interesting features in
   Apache 1.3. Its a way to build Apache modules as so-called <CODE>dynamic
  -shared objects</CODE> (usually named <EM>modulename</EM><CODE>.so</CODE>) which can be loaded via the <CODE>LoadModule</CODE> directives from within Apache's
  -<CODE>httpd.conf</CODE> file. The benefit is that the modules is part of the
  -<CODE>httpd</CODE> program only on-demand, i.e. only when the user wants the module it is
  -loaded into the address space of the <CODE>httpd</CODE>
  -module. This is for instance interesting for memory consumption and easy
  +shared objects</CODE> (usually named <EM>modulename</EM><CODE>.so</CODE>) which can be loaded via the <CODE>LoadModule</CODE> directive in Apache's <CODE>httpd.conf</CODE> file. The benefit is that the modules are part of the <CODE>httpd</CODE> program only on demand, i.e. only when the user wants a module is it loaded
  +into the address space of the <CODE>httpd</CODE> executable. This is interesting for instance in memory consumption and
   upgrade issues.
   
   <P>
  -The DSO mechanism is provided by Apache's <CODE>mod_so.c</CODE> which needs to be compiled into the <CODE>httpd</CODE> program. This is automatically done when DSO is enabled for module <CODE>mod_xxx</CODE> via <CODE>configure
  +The DSO mechanism is provided by Apache's <CODE>mod_so</CODE> module which needs to be compiled into the <CODE>httpd</CODE> binary. This is done automatically when DSO is enabled for module <CODE>mod_xxx</CODE> via <CODE>configure
   --enable-module=xxx</CODE> or by explicitly adding <CODE>mod_so</CODE> via <CODE>configure
   --enable-module=so</CODE>.
   
   <P><DT><STRONG><A NAME="item_APache">APache eXtenSion (APXS) support tool</A></STRONG><DD>
   <P>
   This is a new support tool from Apache 1.3 which can be used to build an
  -Apache module as a DSO even <STRONG>outside</STRONG> the Apache source-tree. One can say APXS is what MakeMaker and XS is for
  -Perl. It knows the platform dependent build parameters for making DSO files
  -and provides an easy way to run the build commands with them.
  +Apache module as a DSO even <STRONG>outside</STRONG> the Apache source-tree. One can say <CODE>APXS</CODE> is for Apache what <CODE>MakeMaker</CODE> and <CODE>XS</CODE> is for Perl. It knows the platform dependent build parameters for making
  +DSO files and provides an easy way to run the build commands with them.
   
   </DL>
   <P>
   Taking these four features together provides a way to integrate mod_perl
  -into Apache in a very clean and smooth way. <EM>No patching of
  -the Apache source tree is needed in the standard situation and even
  -not only the source tree itself is needed in the APXS situation</EM>.
  -
  -<P>
  -To benefit from the above described features a new hybrid build environment
  -was created for the Apache-side of mod_perl. The Apache-side consists of
  -the C source files of mod_perl which have to be compiled into the <CODE>httpd</CODE> program. They are usually copied to the subdirectory <CODE>src/modules/perl/</CODE> in the Apache source tree. To integrate this subtree into the Apache build
  -process a lot of adjustments were done by mod_perl's <CODE>Makefile.PL</CODE> in the past. And additionally the <CODE>Makefile.PL</CODE> controlled the Apache build process.
  -
  -<P>
  -The side-effect of this approach was that it is both a not very clean and
  -especially captive way. Because it assumed mod_perl is the only third-party
  -modules which has to be integrated into Apache. This is very problematic.
  -
  -<P>
  -The new approach described below avoids these problems. It only prepares
  -the <CODE>src/modules/perl/</CODE> subtree inside the Apache source tree <EM>without</EM> adjusting or editing anything else. This way no conflicts can occur.
  -Instead mod_perl is activated (and then configures itself) when the Apache
  -source tree is configured via standard APACI calls later.
  +into Apache in a very clean and smooth way.  <EM>No patching of
  +the Apache source tree is needed in the standard situation and in the
  +APXS situation not even the Apache source tree is needed</EM>.
  +
  +<P>
  +To benefit from the above features a new hybrid build environment was
  +created for the Apache side of mod_perl. The Apache-side consists of the C
  +source files of mod_perl which have to be compiled into the
  +<CODE>httpd</CODE> program. They are usually copied to the subdirectory
  +<CODE>src/modules/perl/</CODE> in the Apache source tree. To integrate this subtree into the Apache build
  +process a lot of adjustments were done by mod_perl's <CODE>Makefile.PL</CODE> in the past. And additionally the
  +<CODE>Makefile.PL</CODE> controlled the Apache build process.
  +
  +<P>
  +This approach is problematic in several ways. It is not very clean. Because
  +it is assumed that mod_perl is the only third-party module which has to be
  +integrated into Apache, it is very restrictive.
  +
  +<P>
  +The new approach described below avoids these problems. It prepares only
  +the <CODE>src/modules/perl/</CODE> subtree inside the Apache source tree
  +<EM>without</EM> adjusting or editing anything else. This way, no conflicts can occur.
  +Instead, mod_perl is activated later (when the Apache source tree is
  +configured, via APACI calls) and then it configures itself.
   
   <P>
   We will return to each of the above configuration mechanisms when
  @@ -362,8 +375,8 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H3><A NAME="Configuration_parameters">Configuration parameters</A></H3></CENTER>
   <P>
  -<CODE>perl Makefile.PL</CODE> accepts various parameters. In this section we will learn what are they and
  -when should they be used.
  +<CODE>perl Makefile.PL</CODE> accepts various parameters. In this section we will learn what they are,
  +and when should they be used.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -372,18 +385,18 @@
   You will be asked the following question during the configuration stage:
   
   <P>
  -<PRE>  &quot;Configure mod_perl with ../apache_xxx/src ?&quot;
  +<PRE>  &quot;Configure mod_perl with ../apache_x.x.x/src ?&quot;
   </PRE>
   <P>
   <CODE>APACHE_SRC</CODE> should be used to define the Apache's source tree directory. For example:
   
   <P>
  -<PRE>  APACHE_SRC=../apache-x.x.x/src
  +<PRE>  APACHE_SRC=../apache_x.x.x/src
   </PRE>
   <P>
   Unless <CODE>APACHE_SRC</CODE> specified, <EM>Makefile.PL</EM> makes an intelligent guess by looking at the directories at the same level
  -as mod_perl sources and suggests a directory with the highest version of
  -Apache found there.
  +as the mod_perl sources and suggests a directory with the highest version
  +of Apache found there.
   
   <P>
   Answering <EM>'y'</EM> confirms either <EM>Makefile.PL</EM>'s guess about the location of the tree, or the directory you have
  @@ -391,21 +404,21 @@
   <CODE>APACHE_SRC</CODE>.
   
   <P>
  -If you use <CODE>DO_HTTPD=1</CODE> or <CODE>NO_HTTPD</CODE> -- the first apache source tree found or the one you have defined will be
  +If you use <CODE>DO_HTTPD=1</CODE> or <CODE>NO_HTTPD</CODE>, the first apache source tree found or the one you have defined will be
   used for the rest of the build process.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H4><A NAME="DO_HTTPD_NO_HTTPD_PREP_HTTPD">DO_HTTPD, NO_HTTPD, PREP_HTTPD</A></H4></CENTER>
   <P>
  -Unless any of <CODE>DO_HTTPD</CODE>, <CODE>NO_HTTPD</CODE> or <CODE>PREP_HTTPD</CODE> used you will be prompted by the following question:
  +Unless any of <CODE>DO_HTTPD</CODE>, <CODE>NO_HTTPD</CODE> or <CODE>PREP_HTTPD</CODE> is used, you will be prompted by the following question:
   
   <P>
  -<PRE>  &quot;Shall I build httpd in ../apache-x.x.x/src for you?&quot;
  +<PRE>  &quot;Shall I build httpd in ../apache_x.x.x/src for you?&quot;
   </PRE>
   <P>
   Answering <EM>'y'</EM> will make sure an httpd binary will be built in
  -<EM>../apache-x.x.x/src</EM> when running <CODE>make</CODE>.
  +<EM>../apache_x.x.x/src</EM> when you run <CODE>make</CODE>.
   
   <P>
   To avoid this prompt when the answer is <EM>Yes</EM> use:
  @@ -414,14 +427,14 @@
   <PRE>  DO_HTTPD=1
   </PRE>
   <P>
  -Note that if you set <CODE>DO_HTTPD=1</CODE>, but not used
  -<CODE>APACHE_SRC=../apache-x.x.x/src</CODE> -- the first apache source tree found will be used to configure and build
  +Note that if you set <CODE>DO_HTTPD=1</CODE>, but do not use
  +<CODE>APACHE_SRC=../apache_x.x.x/src</CODE> then the first apache source tree found will be used to configure and build
   against.
   
   <P>
  -<CODE>PREP_HTTPD=1</CODE> just means default '<CODE>n</CODE>' to the second prompt -- meaning, <EM>do not build httpd (make) in the apache source tree</EM>. But it still will ask you about Apache's source location even if you have
  +<CODE>PREP_HTTPD=1</CODE> just means default '<CODE>n</CODE>' to the second prompt, meaning <EM>do not build (make) httpd in the Apache source tree</EM>. But it still will ask you about Apache's source location even if you have
   used the <CODE>APACHE_SRC</CODE> parameter. Providing the <CODE>APACHE_SRC</CODE>
  -parameter will just save <CODE>perl Makefile.PL</CODE> a need to make a guess.
  +parameter will just eliminate the need for <CODE>perl Makefile.PL</CODE> to make a guess.
   
   <P>
   To avoid the two prompts and avoid building httpd, use:
  @@ -430,18 +443,20 @@
   <PRE>  NO_HTTPD=1
   </PRE>
   <P>
  -If you choose not to build the binary, you will have to do that manually.
  -We will talk about it later. In any case, you need to run
  -<CODE>make install</CODE> in the mod_perl source tree, so the perl side of mod_perl will be
  -installed. Certainly, <CODE>make test</CODE> wouldn't work until before you get the server built.
  +If you choose not to build the binary you will have to do that manually. We
  +will talk about it later. In any case you will need to run <CODE>make install</CODE> in the mod_perl source tree, so the Perl side of mod_perl will be
  +installed. Note that, <CODE>make test</CODE> won't work until you have built the server.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H4><A NAME="Callback_Hooks">Callback Hooks</A></H4></CENTER>
   <P>
  -By default, all callback hooks except for <CODE>PerlHandler</CODE> are turned off. You may edit <EM>src/modules/perl/Makefile</EM>, or enable when running <CODE>perl Makefile.PL</CODE>.
  +META: Refer to/explain callback hooks term
   
   <P>
  +By default, all callback hooks except for <CODE>PerlHandler</CODE> are turned off. You may enable them by editing <EM>src/modules/perl/Makefile</EM>, or when running <CODE>perl Makefile.PL</CODE>.
  +
  +<P>
   Possible parameters are:
   
   <P>
  @@ -468,7 +483,8 @@
     PERL_SSI
   </PRE>
   <P>
  -As with any parameters that are either defined or not, use <CODE>foo=1</CODE> to enable them (e.g. <CODE>PERL_AUTHEN=1</CODE>).
  +As with any parameters that are either defined or not, use
  +<CODE>PERL_hookname=1</CODE> to enable them (e.g. <CODE>PERL_AUTHEN=1</CODE>).
   
   <P>
   To enable all callback hooks use:
  @@ -480,7 +496,7 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H4><A NAME="EVERYTHING">EVERYTHING</A></H4></CENTER>
   <P>
  -To enable all possible hooks, set:
  +To enable everything set:
   
   <P>
   <PRE>  EVERYTHING=1
  @@ -494,10 +510,13 @@
   
   
   <P>
  +META: add a Reference to tracing (doesn't exist yet)
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H4><A NAME="APACHE_HEADER_INSTALL">APACHE_HEADER_INSTALL</A></H4></CENTER>
   <P>
  -By default, the Apache headers files are installed into
  +By default, the Apache source headers files are installed into the
   <EM>$Config{sitearchexp}/auto/Apache/include</EM> directory.
   
   <P>
  @@ -516,10 +535,10 @@
   <CENTER><H4><A NAME="PERL_STATIC_EXTS">PERL_STATIC_EXTS</A></H4></CENTER>
   <P>
   Normally, if an extension is linked static with Perl it is listed in
  -<CODE>Config.pm</CODE>'s <CODE>$Config{static_exts}</CODE>, in which case, mod_perl will also link this extension static with httpd.
  +<CODE>Config.pm</CODE>'s <CODE>$Config{static_exts}</CODE>, in which case mod_perl will also link this extension static with httpd.
   However, if an extension is linked static with Perl after it is installed,
  -it is not listed in Config.pm. You may either edit Config.pm and add these
  -extensions, or configure mod_perl like so:
  +it is not listed in
  +<CODE>Config.pm</CODE>. You may either edit <CODE>Config.pm</CODE> and add these extensions, or configure mod_perl like this:
   
   <P>
   <PRE> perl Makefile.PL &quot;PERL_STATIC_EXTS=Something::Static Another::One&quot; 
  @@ -530,20 +549,19 @@
   <P>
   Generally for <CODE>Apache::Registry</CODE> scripts, the reported line number for warnings and errors that end up in
   the <EM>error_log</EM> file is not correct. This is due to the fact that <CODE>Apache::Registry</CODE>
  -auto-magically wraps the scripts running under its handler into a special
  -code that enables the caching of the compiled scripts. 
  +auto-magically wraps the scripts running under its handler in special code
  +that enables the caching of the compiled scripts.
   
   <P>
  -If configured with <CODE>PERL_MARK_WHERE=1</CODE>, mod_perl will attempt to show the exact line the error or warning
  -happened at.
  +If configured with <CODE>PERL_MARK_WHERE=1</CODE>, mod_perl will attempt to compensate for this effect and show the exact
  +line which triggered the error or warning.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H4><A NAME="APACI_ARGS">APACI_ARGS</A></H4></CENTER>
   <P>
  -When you use &lt;USE_APACI=1&gt; parameter, you can tell the <CODE>perl
  -Makefile.PL</CODE> to pass any arguments you want to the Apache's 
  -<CODE>./configure</CODE> utility, e.g:
  +When you use the <CODE>USE_APACI=1</CODE> parameter, you can tell <CODE>Makefile.PL</CODE>
  +to pass any arguments you want to the Apache <CODE>./configure</CODE> utility, e.g:
   
   <P>
   <PRE>  % perl Makefile.PL USE_APACI=1 \
  @@ -555,29 +573,31 @@
            --proxycachedir=/usr/local/var/httpd_perl/proxy
   </PRE>
   <P>
  -Notice that <STRONG>all</STRONG>  <CODE>APACI_ARGS</CODE> (above) must be passed as one long line if you work with <CODE>t?csh</CODE>!!! However it works correctly the way it shown above with <CODE>(ba)?sh</CODE> (by breaking the long lines with '<CODE>\</CODE>'). If you work with <CODE>t?csh</CODE> it does not work, since <CODE>t?csh</CODE>
  -passes <CODE>APACI_ARGS</CODE> arguments to <CODE>./configure</CODE> by keeping the new lines untouched, but stripping the original '<CODE>\</CODE>', which makes the all the arguments but the first one, ignored by the
  -configuration process.
  +Notice that <STRONG>all</STRONG>  <CODE>APACI_ARGS</CODE> (above) must be passed as one long line if you work with <CODE>t?csh</CODE>!!! However it works correctly as shown above (breaking the long lines with
  +'<CODE>\</CODE>') with <CODE>(ba)?sh</CODE>. If you use <CODE>t?csh</CODE> it does not work, since <CODE>t?csh</CODE> passes the <CODE>APACI_ARGS</CODE>
  +arguments to <CODE>./configure</CODE> leaving the newlines untouched, but stripping the backslashes. This causes
  +all the arguments except the first to be ignored by the configuration
  +process.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H4><A NAME="APACHE_PREFIX">APACHE_PREFIX</A></H4></CENTER>
   <P>
  -If you want to use a non-default Apache installation prefix, use
  -<CODE>APACHE_PREFIX</CODE> parameter, e.g.:
  +If you want to use a non-default Apache installation directory, use the <CODE>APACHE_PREFIX</CODE> parameter, e.g.:
   
   <P>
   <PRE>  % perl Makefile.PL APACHE_PREFIX=/usr/local/ [...]
   </PRE>
   <P>
  -Should be used together with <A HREF="././install.html#APACI_ARGS">APACI_ARGS</A> option.
  +This should be used together with the <A HREF="././install.html#APACI_ARGS">APACI_ARGS</A>
  +option.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H3><A NAME="Reusing_Configuration_Parameters">Reusing Configuration Parameters</A></H3></CENTER>
   <P>
  -It's quite hard to remember what parameters were used in mod_perl build,
  -when you have to upgrade the server. So it's better to save them into a
  +When you have to upgrade the server, it's quite hard to remember what
  +parameters were used in a mod_perl build. So it's better to save them in a
   file. For example if you create a file at
   <EM>~/.mod_perl_build_options</EM>, with contents:
   
  @@ -593,9 +613,9 @@
     % make &amp;&amp; make test &amp;&amp; make install
   </PRE>
   <P>
  -But wait, mod_perl has a standard method to perform the above trick. If a
  -file name <EM>makepl_args.mod_perl</EM> is found in the same directory as the mod_perl build location with any of
  -these options, it will be read in by <EM>Makefile.PL</EM>.
  +But mod_perl has a standard method to perform this trick. If a file named <EM>makepl_args.mod_perl</EM> is found in the same directory as the mod_perl build location with any of
  +these options, it will be read in by <EM>Makefile.PL</EM>. Parameters supplied at the command line will override the parameters
  +given in this file.
   
   <P>
   <PRE>  % ls -1 /usr/src
  @@ -615,20 +635,20 @@
   Now the parameters from <EM>makepl_args.mod_perl</EM> file will be used, as if they were directly typed in.
   
   <P>
  -You can put this file into your home directory and then you should call
  -prefix it with a leading dot:
  +Notice that this file can be located in your home directory or in the
  +<EM>../</EM> directory relative to the mod_perl distribution directory. This file can
  +also start with dot (<EM>.makepl_args.mod_perl</EM>) so you can nicely keep it along with the rest of the dot files in your
  +home directory.
   
   <P>
  -<PRE>  .makepl_args.mod_perl
  -</PRE>
  -<P>
   There is a sample <EM>makepl_args.mod_perl</EM> in the <EM>eg/</EM> directory of mod_perl distribution package, in which you might find a few
   options to enable experimental features to play with too!
   
   <P>
  -But if you have found yourself with a compiled mod_perl and no traces of
  -the specified parameters left, usually you can still find them out, if the
  -sources were not <CODE>make clean</CODE>'d. You will find the Apache specific parameters in <CODE>apache_x.x.x/config.status</CODE> and mod_perl's at in <CODE>mod_perl_x.xx/apaci/mod_perl.config</CODE>.
  +If you are faced with a compiled Apache and no trace of the parameters used
  +to build it, you can usually still find them if the sources were not <CODE>make clean</CODE>'d. You will find the Apache specific parameters in
  +<CODE>apache_x.x.x/config.status</CODE> and the mod_perl parameters in
  +<CODE>mod_perl_x.xx/apaci/mod_perl.config</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -636,14 +656,13 @@
   <P>
   To find out whether some parameter was included in the server, you can take
   a look at the symbols inside the httpd executable with help of
  -<CODE>nm</CODE> or similar utility. For example if you want to see whether you have enabled <CODE>PERL_AUTH=1</CODE> while building the mod_perl, you do:
  +<CODE>nm</CODE> or a similar utility. For example if you want to see whether you enabled <CODE>PERL_AUTH=1</CODE> while building mod_perl, you do:
   
   <P>
   <PRE>  % nm httpd | grep perl_authenticate
   </PRE>
   <P>
  -But it would work if you have an unstripped httpd binary. <CODE>make
  -install</CODE> by default strips the binary before installing it.
  +But this will only work if you have an unstripped httpd binary. By default, <CODE>make install</CODE> strips the binary before installing it.
   
   <P>
   Another approach is to configure <A HREF="././debug.html#Apache_Status_Embedded_inter">/perl-status location</A> and run <A
  @@ -652,22 +671,25 @@
   
   <P>
   Yet another approach is to try to use this parameter in the configuration
  -file, and if it wasn't enabled Apache will tell you that, when you will
  -start the server, by reporting an unknown directive (e.g. when you attempt
  -to use <CODE>PerlAuthenHandler</CODE> handler without building with <CODE>PERL_AUTHEN=1</CODE> parameter)
  +file. If it wasn't enabled Apache will tell you when you will start the
  +server, by reporting an unknown directive.
   
   <P>
  +Similarly, for example, when you attempt to use <CODE>PerlAuthenHandler</CODE>
  +without building Apache with the <CODE>PERL_AUTHEN=1</CODE> parameter, Apache will give an error message.
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H3><A NAME="Using_an_alternative_Configurati">Using an alternative Configuration file</A></H3></CENTER>
  +<CENTER><H3><A NAME="Using_an_Alternative_Configurati">Using an Alternative Configuration File</A></H3></CENTER>
   <P>
  -By default mod_perl provides its own copy of <EM>Configuration</EM> file to Apache's <CODE>./configure</CODE> utility. If you wish to pass it your own copy, do:
  +By default mod_perl provides its own copy of the <EM>Configuration</EM> file to Apache's <CODE>./configure</CODE> utility. If you wish to pass it your own copy, do this:
   
   <P>
   <PRE>  % perl Makefile.PL CONFIG=Configuration.custom
   </PRE>
   <P>
  -Where <STRONG>Configuration.custom</STRONG> is the name of any file relative to the apache source tree you build
  -against.
  +Where <CODE>Configuration.custom</CODE> is the full pathname of the file
  +<EM>relative to the Apache source tree you build against</EM>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -689,11 +711,11 @@
   <P>
   you've got a problem with your compiler. There is chance that it's
   improperly installed or not installed at all. Sometimes the reason is that
  -your perl executable was built on a different machine, and the software
  -installed on your maching is not the same. Generally this happens when you
  -install the prebuilt packages, like RPM or DEB. What happens is that the
  -dependencies weren't properly defined in the perl binary package and you
  -were allowed to install it, while some essential package is not installed.
  +your Perl executable was built on a different machine, and the software
  +installed on your machine is not the same. Generally this happens when you
  +install the prebuilt packages, like RPM or DEB. The dependencies weren't
  +properly defined in the Perl binary package and you were allowed to install
  +it, although some essential package is not installed.
   
   <P>
   The most frequent pitfall is a missing gdbm library. See <A HREF="././install.html#Missing_or_Misconfigured_libgdbm">Missing or Misconfigured libgdbm.so</A> for more info.
  @@ -701,7 +723,7 @@
   <P>
   But why guess, when we can actually see the real error message and
   understand what the real problem is. To get a real error message, edit the
  -Apache <EM>src/Configure</EM> script. Down around line 2140 you will see a line like:
  +Apache <EM>src/Configure</EM> script. Down around line 2140 you will see a line like this:
   
   <P>
   <PRE>   if ./helpers/TestCompile sanity; then
  @@ -720,13 +742,13 @@
   <CENTER><H4><A NAME="Missing_or_Misconfigured_libgdbm">Missing or Misconfigured libgdbm.so</A></H4></CENTER>
   <P>
   On some RedHat systems you might encounter a problem during the <CODE>perl
  -Makefile.PL</CODE> stage, when the installed perl was built with <CODE>gdbm</CODE>
  +Makefile.PL</CODE> stage, when the installed Perl was built with the <CODE>gdbm</CODE>
   library, but the library isn't actually installed. If this is your
  -situation make sure you install it, before proceeding with the build
  +situation make sure you install it before proceeding with the build
   process.
   
   <P>
  -You can check how the Perl was built, by running <CODE>perl -V</CODE> command:
  +You can check how Perl was built by running the <CODE>perl -V</CODE> command:
   
   <P>
   <PRE>  % perl -V | grep libs
  @@ -738,14 +760,14 @@
   <PRE>  libs=-lnsl -lndbm -lgdbm -ldb -ldl -lm -lc -lposix -lcrypt
   </PRE>
   <P>
  -Sometimes the problem is even more obscure, you do have libgdbm installed
  -but it's not properly installed. Take a look at:
  +Sometimes the problem is even more obscure: you do have <CODE>libgdbm</CODE>
  +installed but it's not properly installed. Do this:
   
   <P>
   <PRE>  % ls /usr/lib/libgdbm.so*
   </PRE>
   <P>
  -If you get all three files like I do:
  +If you get at least three lines like I do:
   
   <P>
   <PRE>  lrwxrwxrwx   /usr/lib/libgdbm.so -&gt; libgdbm.so.2.0.0
  @@ -770,8 +792,14 @@
   Now you should be able to build mod_perl without any problems.
   
   <P>
  +Note that the symbolic link 
  +
  +<P>
  +<PRE>  lrwxrwxrwx   /usr/lib/libgdbm.so.2 -&gt; libgdbm.so.2.0.0
  +</PRE>
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H4><A NAME="undefined_reference_to_PL_perl_">undefined reference to `PL_perl_destruct_level'</A></H4></CENTER>
  +<CENTER><H4><A NAME="Undefined_reference_to_PL_perl_">Undefined reference to `PL_perl_destruct_level'</A></H4></CENTER>
   <P>
   When manually building mod_perl using the shared library:
   
  @@ -802,75 +830,73 @@
     mod_perl.o(.text+0x102): undefined reference to `PL_perl_destruct_level'
     mod_perl.o(.text+0x10c): undefined reference to `PL_perl_destruct_level'
     mod_perl.o(.text+0x13b): undefined reference to `Perl_av_undef'
  -  [more error snipped]
  +  [more errors snipped]
   </PRE>
   <P>
  -This happens when you have perl built statically linked, with no shared <EM>libperl.a</EM>. Build a dynamically linked perl with <EM>libperl.a</EM>
  -and the problems will disappear.
  +This happens when you have Perl built statically linked, with no shared <EM>libperl.a</EM>. Build a dynamically linked Perl (with
  +<EM>libperl.a</EM>) and the problem will disappear.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="mod_perl_Building_make_">mod_perl Building (make)</A></H2></CENTER>
   <P>
  -After configuration completion you build the server, by calling:
  +After completing the configuration you build the server, by calling:
   
   <P>
   <PRE>  % make
   </PRE>
   <P>
  -which compiles the source files and creates an httpd binary or/and a
  -separate library for each module, which can be loaded at run time or
  -inserted into the httpd binary sometime later when the <CODE>make</CODE> will be called from Apache source directory.
  +which compiles the source files and creates an httpd binary and/or a
  +separate library for each module, which can either be inserted into the
  +httpd binary when <CODE>make</CODE> is called from Apache source directory or loaded later, at run time.
   
   <P>
  -Note: it's important that you don't put the mod_perl source tree, inside
  -the Apache's sources subdirectory -- since Apache::src seems to not work
  -then!
  +Note: don't put the mod_perl directory inside the Apache directory, since <CODE>Apache::src</CODE> won't work then!
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H3><A NAME="make_Troubleshooting">make Troubleshooting</A></H3></CENTER>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H4><A NAME="undefined_reference_to_Perl_new">undefined reference to 'Perl_newAV'</A></H4></CENTER>
  +<CENTER><H4><A NAME="Undefined_reference_to_Perl_new">Undefined reference to 'Perl_newAV'</A></H4></CENTER>
   <P>
  -This and similar error messages show up during <CODE>make</CODE> process. Generally happens when you have a broken Perl installation. Make
  -sure it's not installed from a broken RPM or another binary package, if it
  -is -- build Perl from source or use another properly built binary package.
  -Run <CODE>perl -V</CODE> to learn what version of Perl you are using and other important details.
  +This and similar error messages may show up during the <CODE>make</CODE>
  +process. Generally it happens when you have a broken Perl installation.
  +Make sure it's not installed from a broken RPM or another binary package.
  +If it is, build Perl from source or use another properly built binary
  +package. Run <CODE>perl -V</CODE> to learn what version of Perl you are using and other important details.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H4><A NAME="unrecognized_format_specifier_fo">unrecognized format specifier for...</A></H4></CENTER>
  +<CENTER><H4><A NAME="Unrecognized_format_specifier_fo">Unrecognized format specifier for...</A></H4></CENTER>
   <P>
   <PRE>  From: Scott Fagg &lt;scott.fagg@arup.com.au&gt;
     
     I'm using apache 1.3.9 , mod_fastcgi 2.2.2 and mod_perl 1.21
     
  -  Originally my build of these three together worked, however when i
  -  went to rebuild a few months later i recieved a lot of &quot;unrecognized
  -  format specifier&quot; errors. A search of the internet showed that i
  -  wasn't the only one but i couldn't find a solution mentioned.
  +  Originally my build of these three together worked, however when I
  +  went to rebuild a few months later I recieved a lot of &quot;unrecognized
  +  format specifier&quot; errors.  A search of the internet showed that I
  +  wasn't the only one but I couldn't find a solution mentioned.
     
  -  Puzzled i tried to track down the problem. Using clean source i
  -  could build apache/mod_perl/mod_fastcgi on my RedHat 5.2 workstation
  -  but never on my RedHat
  -  5.2 server.
  +  Puzzled, I tried to track down the problem.  Using clean source I
  +  could build Apache/mod_perl/mod_fastcgi on my RedHat 5.2 workstation
  +  but never on my RedHat 5.2 server.
     
  -  The only tinkering i'd done with the server was to use SFIO to
  -  rebuild perl and get mod_fastcgi working the first time i used
  -  fastcgi.
  +  The only tinkering I'd done with the server was to use SFIO to
  +  rebuild Perl and get mod_fastcgi working the first time I used
  +  FastCGI.
     
  -  By removing the SFIO .h files, the apache/mod_perl compile would get
  -  further and the 'unrecognized format specifier' errors disappeared,
  -  but naturally other pieces of code refused to compile complaining
  -  about the missing sfio files.
  +  By removing the C&lt;sfio&gt; .h files, the Apache/mod_perl compile would
  +  get further and the 'unrecognized format specifier' errors
  +  disappeared, but naturally other pieces of code refused to compile
  +  complaining about the missing C&lt;sfio&gt; files.
     
     A quick check of the mod_fast site noted that it no longer needed
  -  SFIO, so i removed it and replaced my rebuilt sfio-perl binaries
  +  SFIO, so I removed it and replaced my rebuilt sfio-perl binaries
     with clean ones (from a redhat RPM) and was able to rebuild apache
  -  with mod_perl + mod_fastcgi ( + php) All of my mod_perl stuff works
  -  and so too does my fastcgi.
  +  with mod_perl+mod_fastcgi (+php). All of my mod_perl stuff works and
  +  so too does my fastcgi.
     
     Hope that helps some one. I wasn't able to find any answers to the
     problem while searching the net.
  @@ -879,63 +905,62 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Built_Server_Testing_make_test_">Built Server Testing (make test)</A></H2></CENTER>
   <P>
  -After building the server, it's a good idea to throughly test it, by
  +After building the server, it's a good idea to test it throughly, by
   calling:
   
   <P>
   <PRE>  % make test
   </PRE>
   <P>
  -Fortunately mod_perl comes with a bunch of tests, which attempt to try to
  -use all the features you asked for at the configuration stage. If any of
  -the test fails, the <CODE>make test</CODE> stage would fail.
  +Fortunately mod_perl comes with a bunch of tests, which attempt to use all
  +the features you asked for at the configuration stage. If any of the test
  +fails, the <CODE>make test</CODE> stage will fail.
   
   <P>
   Running <CODE>make test</CODE> will start a freshly built httpd on port 8529 running under the uid and gid
  -of the <CODE>perl Makefile.PL</CODE> process, the httpd will be terminated when the tests are finished.
  +of the <CODE>perl Makefile.PL</CODE> process. The httpd will be terminated when the tests are finished.
   
   <P>
   Each file in the testing suite generally includes more than one test, but
  -when you do the testing, the program will solely report how many were
  +when you do the testing, the program will solely report how many tests were
   passed and the total number of tests defined in the test file. However if
   not all the tests in the file fail you want to know which ones did. To gain
  -this information, you should run the tests in a verbose mode. You can
  -enable this mode by using <CODE>TEST_VERBOSE</CODE>
  +this information you should run the tests in verbose mode. You can enable
  +this mode by using the <CODE>TEST_VERBOSE</CODE>
   parameter:
   
   <P>
   <PRE>  % make test TEST_VERBOSE=1
   </PRE>
   <P>
  -To change the default port the testing happens on (8529 as of this
  -writing), do:
  +To change the default port (8529) used for the test do this:
   
   <P>
   <PRE>  % perl Makefile.PL PORT=xxxx
   </PRE>
   <P>
  -To simply start the newly built httpd run:
  +To start the newly built Apache:
   
   <P>
   <PRE>  % make start_httpd
   </PRE>
   <P>
  -To shutdown this httpd run:
  +To shutdown Apache:
   
   <P>
   <PRE>  % make kill_httpd
   </PRE>
   <P>
  -NOTE to Ben-SSL users: httpsd does not seem to handle <EM>/dev/null</EM> as the location of certain files, you'll have to change these by hand.
  -Tests are run with <CODE>SSLDisable</CODE> directive.
  +NOTE to Ben-SSL users: httpsd does not seem to handle <EM>/dev/null</EM> as the location of certain files (for example some of the configuration
  +files mentioned in <EM>httpd.conf</EM> can be ignored by reading them from
  +<EM>/dev/null</EM>) so you'll have to change these by hand. The tests are run with the <CODE>SSLDisable</CODE> directive.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H3><A NAME="Manual_Testing">Manual Testing</A></H3></CENTER>
   <P>
  -Tests are invoked by running the <CODE>./TEST</CODE> script located at <EM>./t</EM>
  -directory. Use -v option for verbose tests. You might run an individual
  -test like this:
  +Tests are invoked by running the <CODE>./TEST</CODE> script located in the
  +<EM>./t</EM> directory. Use the <EM>-v</EM> option for verbose tests. You might run an individual test like this:
   
   <P>
   <PRE>  % t/TEST -v modules/file.t
  @@ -947,8 +972,8 @@
   <PRE>  % t/TEST modules
   </PRE>
   <P>
  -<CODE>TEST</CODE> script worries to start the server before the test is getting executed. If
  -for some reason it fails, use <CODE>make start_httpd</CODE> to start it explicitly.
  +The <CODE>TEST</CODE> script starts the server before the test is executed. If for some reason it
  +fails to start, use <CODE>make start_httpd</CODE> to start it explicitly.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -957,23 +982,22 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H4><A NAME="make_test_fails">make test fails</A></H4></CENTER>
   <P>
  -You cannot run <CODE>make test</CODE> before you build the httpd, if you told
  -<CODE>perl Makefile.PL</CODE> not to build the httpd executable, there is no httpd to make the test
  -against. Go to Apache source tree and run
  -<CODE>make</CODE>, then return to mod_perl source tree and continue with server testing.
  +You cannot run <CODE>make test</CODE> before you build Apache, so if you told
  +<CODE>perl Makefile.PL</CODE> not to build the httpd executable, there is no httpd to run the test
  +against. Go to the Apache source tree and run
  +<CODE>make</CODE>, then return to the mod_perl source tree and continue with the server
  +testing.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H4><A NAME="mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of apache</A></H4></CENTER>
  +<CENTER><H4><A NAME="mod_perl_c_is_incompatible_with_">mod_perl.c is incompatible with this version of Apache</A></H4></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 during the build process. Do run <CODE>find</CODE> (or <CODE>locate</CODE>) utility in order to locate <CODE>ap_mmn.h</CODE> file. In my case I have had a
  -<CODE>/usr/local/include/ap_mmn.h</CODE> which was installed by RedHat install process. If this is the case get rid
  -of it, and rebuild it again.
  +If you had a stale old Apache header layout in one of the <EM>include</EM>
  +paths during the build process you will see this message when you try to
  +execute httpd. Run the <CODE>find</CODE> (or <CODE>locate</CODE>) utility in order to locate the file <EM>ap_mmn.h</EM>. Delete it and rebuild Apache. RedHat installed a copy of <EM>/usr/local/include/ap_mmn.h</EM> on my system.
   
   <P>
  -For all RedHat fans, before you are going to build the apache by yourself,
  -do:
  +For all RedHat fans, before you build Apache yourself, do:
   
   <P>
   <PRE> % rpm -e apache
  @@ -985,11 +1009,10 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H4><A NAME="make_test_skipping_test_on_">make test......skipping test on this platform</A></H4></CENTER>
   <P>
  -While doing <CODE>make test</CODE> you would notice that some of the tests are being reported as skipped. The
  -real reason is that you are missing some optional modules for these test to
  -be passed. For a hint you might want to peek at the content of each test
  +While doing <CODE>make test</CODE> you will notice that some of the tests are reported as <EM>skipped</EM>. The reason is that you are missing some optional modules for these test
  +to be passed. For a hint you might want to peek at the content of each test
   (you will find them all in the <CODE>./t</CODE> directory (mnemonic - t, tests). I'll list a few examples, but of course
  -the requirements might be changed in the future.
  +the requirements may change in the future.
   
   <P>
   <PRE>  modules/cookie......skipping test on this platform
  @@ -1035,64 +1058,61 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H4><A NAME="make_test_fails_due_to_misconfig">make test fails due to misconfigured localhost</A></H4></CENTER>
  +<CENTER><H4><A NAME="make_test_Fails_Due_to_Misconfig">make test Fails Due to Misconfigured localhost Entry</A></H4></CENTER>
   <P>
  -<CODE>make test</CODE> suit uses the <EM>localhost</EM> to accomplish the tests that require network. Make sure you have this exact
  -entry in <EM>/etc/hosts</EM>:
  +The <CODE>make test</CODE> suite uses <EM>localhost</EM> to run the tests that require a network. Make sure you have this entry in <EM>/etc/hosts</EM>:
   
   <P>
   <PRE>  127.0.0.1       localhost.localdomain   localhost
   </PRE>
   <P>
  -Also make sure that you have the loopback device [lo] configured. [hint:
  -try 'ifconfig lo' to test for existance]
  +Also make sure that you have the loopback device [lo] configured. [Hint:
  +try 'ifconfig lo' to test for its existence.]
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Installation_make_install_">Installation (make install)</A></H2></CENTER>
   <P>
   After testing the server, the last step left is to install it. First
  -install all the perl side files:
  +install all the Perl side files:
   
   <P>
   <PRE>   % make install
   </PRE>
   <P>
  -The go to the Apache source tree and complete the Apache files installation
  -(config files, httpd and other utilities):
  +Then go to the Apache source tree and complete the Apache installation
  +(installing the configuration files, httpd and utilities):
   
   <P>
   <PRE>  % cd ../apache_x.x.x
     % make install
   </PRE>
   <P>
  -Now the installation should be considered completed. You may configure your
  -server now and start using it.
  +Now the installation should be considered complete. You may now configure
  +your server and start using it.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Building_Apache_and_mod_perl_by_">Building Apache and mod_perl by Hand</A></H2></CENTER>
   <P>
  -If you wish to process the httpd build separately from the mod_perl, you
  -should use <CODE>NO_HTTPD=1</CODE> option during the <CODE>perl Makefile.PL</CODE>
  -stage, then configure various things by hand and proceed with building
  -process. You shouldn't run <CODE>perl Makefile</CODE> before following the steps described in this section.
  +If you wish to build httpd separately from mod_perl, you should use the <CODE>NO_HTTPD=1</CODE> option during the <CODE>perl Makefile.PL</CODE> (mod_perl build) stage. Then you will need to configure various things by
  +hand and proceed to build Apache. You shouldn't run <CODE>perl Makefile.PL</CODE>
  +before following the steps described in this section.
   
   <P>
  -These are the configurations you should make before the build stage, if you
  -choose to manually build mod_perl:
  +If you choose to manually build mod_perl, there are three things you may
  +need to set up before the build stage:
   
   <DL>
   <P><DT><STRONG><A NAME="item_mod_perl">mod_perl's Makefile</A></STRONG><DD>
   <P>
   When <CODE>perl Makefile.PL</CODE> is executed,
  -<EM>$APACHE_SRC/modules/perl/Makefile</EM> will be modified to enable various options (e.g. ALL_HOOKS=1). Instead of
  -tweaking the options during the the <CODE>perl Makefile.PL</CODE>, you may also edit
  -<EM>mod_perl-x.xx/src/modules/perl/Makefile</EM> before running <CODE>perl
  -Makefile.PL</CODE>.
  +<EM>$APACHE_SRC/modules/perl/Makefile</EM> will be modified to enable various options (e.g. <CODE>ALL_HOOKS=1</CODE>).
   
   <P>
  -This is an optional step.
  +Optionally, instead of tweaking the options during <CODE>perl Makefile.PL</CODE>
  +you may edit <EM>mod_perl-x.xx/src/modules/perl/Makefile</EM> before running
  +<CODE>perl Makefile.PL</CODE>.
   
   <P><DT><STRONG><A NAME="item_Configuration">Configuration</A></STRONG><DD>
   <P>
  @@ -1105,6 +1125,9 @@
   We suggest you add this entry at the end of the <EM>Configuration</EM> file if you want your callback hooks to have precedence over core handlers.
   
   <P>
  +META: Add references to callback hooks/core handlers info.
  +
  +<P>
   Add the following to <CODE>EXTRA_LIBS</CODE>:
   
   <P>
  @@ -1116,7 +1139,7 @@
   <P>
   <PRE>  EXTRA_CFLAGS=`perl -MExtUtils::Embed -e ccopts` 
   </PRE>
  -<P><DT><STRONG><A NAME="item_mod_perl">mod_perl source files</A></STRONG><DD>
  +<P><DT><STRONG><A NAME="item_mod_perl">mod_perl Source Files</A></STRONG><DD>
   <P>
   Return to the mod_perl directory and copy the mod_perl source files into
   the apache build directory:
  @@ -1133,15 +1156,15 @@
      APACHE_SRC=../apache_x.x.x/src
   </PRE>
   <P>
  -<CODE>DYNAMIC=1</CODE> enables a build of a shared mod_perl library. Add other options if
  +<CODE>DYNAMIC=1</CODE> enables a build of the shared mod_perl library. Add other options if
   required.
   
   <P>
   <PRE>  % make install
   </PRE>
   <P>
  -Now you may proceed with plain Apache build process. Note that in order for
  -your changes to the <EM>apache_x.x.x/src/Configuration</EM> file to take effect, you must run <CODE>apache_x.x.x/src/Configure</CODE> instead of the default <EM>apache_x.x.x/configure</EM> script:
  +Now you may proceed with the plain Apache build process. Note that in order
  +for your changes to the <EM>apache_x.x.x/src/Configuration</EM> file to take effect, you must run <CODE>apache_x.x.x/src/Configure</CODE> instead of the default <EM>apache_x.x.x/configure</EM> script:
   
   <P>
   <PRE>  % cd ../apache_x.x.x/src
  @@ -1154,7 +1177,7 @@
   <CENTER><H1><A NAME="Installation_Scenarios_for_Stand">Installation Scenarios for Standalone mod_perl</A></H1></CENTER>
   <P>
   There are various ways available to build Apache with the new hybrid build
  -environment:
  +environment (using <CODE>USE_APACI=1</CODE>):
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -1165,8 +1188,8 @@
   enhancing Apache proceed as before:
   
   <P>
  -<PRE>  % tar zvxf apache_x.x.x.tar.gz
  -  % tar zvxf mod_perl-x.xx.tar.gz
  +<PRE>  % tar xzvf apache_x.x.x.tar.gz
  +  % tar xzvf mod_perl-x.xx.tar.gz
     % cd mod_perl-x.xx
     % perl Makefile.PL APACHE_SRC=../apache_x.x.x/src \
       DO_HTTPD=1 USE_APACI=1 EVERYTHING=1
  @@ -1183,8 +1206,8 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="The_Flexible_Way">The Flexible Way</A></H2></CENTER>
   <P>
  -This is the standard situation when you want to be flexible while building:
  -Statically building mod_perl into the <CODE>httpd</CODE> binary of Apache but via different steps, so you have a chance for other
  +This is the normal situation where you want to be flexible while building.
  +Statically building mod_perl into the Apache binary (<CODE>httpd</CODE>) but via different steps, so you have a chance to include other
   third-party Apache modules, etc.
   
   <OL>
  @@ -1193,8 +1216,8 @@
   The first step is as before extracts the distributions:
   
   <P>
  -<PRE>  % tar zvxf apache_x.x.x.tar.gz
  -  % tar zvxf mod_perl-x.xx.tar.gz
  +<PRE>  % tar xvzf apache_x.x.x.tar.gz
  +  % tar xzvf mod_perl-x.xx.tar.gz
   </PRE>
   <P><LI><STRONG><A NAME="item_Install_mod_perl_s_Perl_side_and">Install mod_perl's Perl-side and prepare the Apache-side</A></STRONG>
   <P>
  @@ -1216,33 +1239,32 @@
    $ cd ..
   </PRE>
   <P>
  -The <CODE>APACHE_SRC</CODE> set the path to your Apache source tree, the
  +The <CODE>APACHE_SRC</CODE> option sets the path to your Apache source tree, the
   <CODE>NO_HTTPD</CODE> option forces this path and only this path to be used, the
   <CODE>USE_APACI</CODE> option triggers the new hybrid build environment and the
  -<CODE>PREP_HTTPD</CODE> forces only a preparation of the
  -<CODE>APACHE_SRC/modules/perl/</CODE> tree but no automatic builds.
  +<CODE>PREP_HTTPD</CODE> option forces preparation of the
  +<CODE>APACHE_SRC/modules/perl/</CODE> tree but no automatic build.
   
   <P>
   Then the configuration process prepares the Apache-side of mod_perl in the
  -Apache source tree but doesn't touch anything else inside it. It then just
  +Apache source tree but doesn't touch anything else in it. It then just
   builds the Perl-side of mod_perl and installs it into the Perl installation
   hierarchy.
   
   <P>
  -Important: If you use <CODE>PREP_HTTPD</CODE> as described above, to complete the build you must go into an apache source
  -directory and run <CODE>make</CODE>
  +Important: If you use <CODE>PREP_HTTPD</CODE> as described above, to complete the build you must go into the Apache
  +source directory and run <CODE>make</CODE>
   and <CODE>make install</CODE>.
   
   <P><LI><STRONG><A NAME="item_Additionally_prepare_other_third">Additionally prepare other third-party modules</A></STRONG>
   <P>
  -Now you still have a chance to prepare more third-party modules. For
  -instance the PHP3 language can be added similarly to the above mod_perl
  -procedure.
  +Now you have a chance to prepare third-party modules. For instance the PHP3
  +language can be added in a manner similar to the mod_perl procedure.
   
  -<P><LI><STRONG><A NAME="item_Build_the_Apache_package">Build the Apache package</A></STRONG>
  +<P><LI><STRONG><A NAME="item_Build_the_Apache_Package">Build the Apache Package</A></STRONG>
   <P>
  -Finally it's a time to build the Apache package and thus also the
  -Apache-side of mod_perl and any other prepared third-party modules:
  +Finally it's time to build the Apache package and thus also the Apache-side
  +of mod_perl and any other third-party modules you've prepared:
   
   <P>
   <PRE> $ cd apache_x.x.x
  @@ -1255,43 +1277,59 @@
    $ make install
   </PRE>
   <P>
  -The <CODE>--prefix</CODE> option is needed if you want to change the default target directory of
  -apache installation and the <CODE>--activate-module</CODE>
  -option activates mod_perl for the configuration process and thus also for
  -the build process.
  +The <CODE>--prefix</CODE> option is needed if you want to change the default target directory of the
  +Apache installation and the
  +<CODE>--activate-module</CODE> option activates mod_perl for the configuration process and thus also for
  +the build process. If you choose
  +<CODE>--prefix=/usr/share/apache</CODE> the Apache directory tree will be installed in <EM>/usr/share/apache</EM>.
   
   <P>
   The last three steps build, test and install the Apache-side of the
  -mod_perl enabled server (probably including other third-party components,
  -otherwise you wouldn't choose this scenario)
  +mod_perl enabled server. Presumably your new server includes third-party
  +components, otherwise you probably won't choose this method of building.
   
   </OL>
   <P>
  -The scenario we just saw enables you to insert mod_perl into Apache without
  -having to mangle the Apache source tree for mod_perl plus the freedom of
  -being able to adding more third-party modules.
  +The method described above enables you to insert mod_perl into Apache
  +without having to mangle the Apache source tree for mod_perl. It also gives
  +you the freedom to add third-party modules.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Build_mod_perl_as_DSO_inside_Apa">Build mod_perl as DSO inside Apache source tree via APACI</A></H2></CENTER>
  +<CENTER><H2><A NAME="Build_mod_perl_as_a_DSO_inside_t">Build mod_perl as a DSO inside the Apache Source Tree via APACI</A></H2></CENTER>
   <P>
  -<STRONG>Warning</STRONG>: With Apache 1.3 there is support for building modules as Dynamic Shared
  -Objects (DSO). So there is support for DSO in mod_perl now, too.  <EM>BUT THIS IS STILL EXPERIMENTAL, SO BE WARNED!</EM>
  +<STRONG>Warning</STRONG>:  <EM>THIS IS STILL EXPERIMENTAL, SO BE WARNED!</EM>
  +
   
   
  +<P>
  +With Apache 1.3 there is support for building modules as Dynamic Shared
  +Objects (DSO). So there is support for DSO in mod_perl now, too. Your
  +mileage may vary. Almost certainly it will.
   
   <P>
  -We already said that the new mod_perl build environment is a hybrid one.
  -What does it mean? It means for instance that the same
  -<CODE>src/modules/perl/</CODE> stuff can be used to build mod_perl as a DSO, too. <EM>And again without having to edit anything specially for
  -this</EM>. When you want to build <CODE>libperl.so</CODE> (sorry for the name,
  -<CODE>libmodperl.so</CODE> would be more correct, but because of historic Apache issues the name has
  -to be <CODE>libperl.so</CODE>. Don't confuse this with the real <CODE>libperl.a</CODE> or even <CODE>libperl.so</CODE> from the Perl installation) all you have to do is to add one single option
  -to the above steps.
  +<STRONG>Warning</STRONG>:  <EM>YOU HAVE BEEN WARNED!</EM>
  +
  +
   
   <P>
  +We have already said that the new mod_perl build environment (<CODE>USE_APACI</CODE>) is a hybrid. What does it mean? It means for instance that the same <CODE>src/modules/perl/</CODE> stuff can be used to build mod_perl as a DSO or not, without having to edit
  +anything especially for this. When you want to build <CODE>libperl.so</CODE> all you have to do is to add one single option to the above steps.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="libperl_so_and_libperl_a">libperl.so and libperl.a</A></H3></CENTER>
  +<P>
  +<CODE>libmodperl.so</CODE> would be more correct for the mod_perl file, but the name has to be <CODE>libperl.so</CODE> because of prehistoric Apache issues. Don't confuse the <CODE>libperl.so</CODE> for mod_perl with the file of the same name which comes with Perl itself.
  +They are two different things. It is unfortunate that they happen to have
  +the same name.
  +
  +<P>
  +There is also a <CODE>libperl.a</CODE> which comes with the Perl installation. That's different too.
  +
  +<P>
   You have two options here, depending on which way you have chosen above: If
  -you choose the All-In-One way from above then add:
  +you choose the All-In-One way from above then add
   
   <P>
   <PRE>  USE_DSO=1
  @@ -1307,24 +1345,25 @@
   
   <P>
   As you can see only an additional <CODE>USE_DSO=1</CODE> or
  -<CODE>--enable-shared=perl</CODE> option is needed. Anything else is done automatically: <CODE>mod_so</CODE> is automatically enabled, the Makefiles are adjusted automatically and even
  -the <CODE>install</CODE> target from APACI now additionally installs the <CODE>libperl.so</CODE> into the Apache installation tree. And even more: The <CODE>LoadModule</CODE> and <CODE>AddModule</CODE> directives (which dynamically load and inserts the mod_perl into a httpd)
  -are automatically added to the <CODE>httpd.conf</CODE> file.
  +<CODE>--enable-shared=perl</CODE> option is needed. Everything else is done automatically: <CODE>mod_so</CODE> is automatically enabled, the Makefiles are adjusted automatically and even
  +the <CODE>install</CODE> target from APACI now additionally installs <CODE>libperl.so</CODE> into the Apache installation tree. And even more: the <CODE>LoadModule</CODE> and <CODE>AddModule</CODE> directives (which dynamically load and insert mod_perl into httpd) are
  +automatically added to <EM>httpd.conf</EM>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Build_mod_perl_as_DSO_outside_Ap">Build mod_perl as DSO outside Apache source tree via APXS</A></H2></CENTER>
  +<CENTER><H2><A NAME="Build_mod_perl_as_a_DSO_outside_">Build mod_perl as a DSO outside the Apache Source Tree via APXS</A></H2></CENTER>
   <P>
  -Above we've seen how to build mod_perl as DSO <EM>inside</EM> the Apache source tree. But there is a nifty alternative: Building mod_perl
  -as DSO <EM>outside</EM> the Apache source tree via the new Apache 1.3 support tool <CODE>apxs</CODE> (APache eXtension). The advantage is obvious: You can extend an already
  +Above we've seen how to build mod_perl as a DSO <EM>inside</EM> the Apache source tree. But there is a nifty alternative: building mod_perl
  +as a DSO <EM>outside</EM> the Apache source tree via the new Apache 1.3 support tool <CODE>apxs</CODE> (APache eXtension). The advantage is obvious: you can extend an already
   installed Apache with mod_perl even if you don't have the sources (for
  -instance you installed an Apache binary package from your vendor).
  +instance, you may have installed an Apache binary package from your
  +vendor).
   
   <P>
  -Here are the building steps:
  +Here are the build steps:
   
   <P>
  -<PRE>  % tar zvxf mod_perl-x.xx.tar.gz
  +<PRE>  % tar xzvf mod_perl-x.xx.tar.gz
     % cd mod_perl-x.xx
     % perl Makefile.PL \
       USE_APXS=1 \
  @@ -1334,7 +1373,7 @@
     % make &amp;&amp; make test &amp;&amp; make install
   </PRE>
   <P>
  -This will build the DSO <CODE>libperl.so</CODE>  <STRONG>outside</STRONG> the Apache source tree with the new Apache 1.3 support tool <CODE>apxs</CODE> and install it into the existing Apache hierarchy.
  +This will build the DSO <CODE>libperl.so</CODE>  <EM>outside</EM> the Apache source tree with the new Apache 1.3 support tool <CODE>apxs</CODE> and install it into the existing Apache hierarchy.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -1344,41 +1383,63 @@
   installation guidelines. Thanks!)
   
   <P>
  -You have seen a very detailed installation scenarios, since mod_perl is
  -used with many other components that plug into Apache, you definitely want
  -to know how to build them together with mod_perl. Since all the steps are
  -simple assuming that you understood how the build process works, I'll show
  -only the commands to be executed, with no comments unless there is
  -something we haven't discussed before.
  +You have now seen very detailed installation instructions for specific
  +cases, but since mod_perl is used with many other components that plug into
  +Apache, you will definitely want to know how to build them together with
  +mod_perl.
   
   <P>
  -Generally each and every scenario that I'm going to show consist of
  -downloading source distributions of components to be used, un-packing them,
  -configuring them and proceeding with Apache build process using the
  -appropriate to each component parameters, followed by <CODE>make test</CODE>
  -and <CODE>make install</CODE>.
  +Since all the steps are simple, and assuming that you now understand how
  +the build process works, I'll show only the commands to be executed with no
  +comments unless there is something we haven't discussed before.
  +
  +<P>
  +Generally every example that I'm going to show consist of:
   
  +<OL>
  +<P><LI>
  +<P>
  +downloading the source distributions of the components to be used
  +
  +<P><LI>
  +<P>
  +un-packing them
  +
  +<P><LI>
  +<P>
  +configuring them
  +
  +<P><LI>
  +<P>
  +building Apache using the parameters appropriate to each component
  +
  +<P><LI>
  +<P>
  +<CODE>make test</CODE> and <CODE>make install</CODE>.
  +
  +</OL>
   <P>
  -All these scenarios were tested on Linux platform, you might need to refer
  -to the specific component's documentation if something doesn't work for you
  -as described below. The intention of this section is not to show how to
  -install other non-mod_perl components alone, but how to do this in bundle
  -with mod_perl.
  +All these scenarios were tested on a Linux platform, you might need to
  +refer to the specific component's documentation if something doesn't work
  +for you as described below. The intention of this section is not to show
  +how to install other non-mod_perl components alone, but how to do this in a
  +bundle with mod_perl.
   
   <P>
  -Also, notice that the links I've used below are likely to change when you
  -read this document. That's why I have used the <EM>x.x.x</EM>
  -convention, instead of using hardcoded version numbers. Remember to replace <EM>x.xx</EM> place-holders with version numbers of the distributions you are about to
  -use. To find out the latest stable version number, visit the components
  +Also, notice that the links I've used below are very likely to have changed
  +by the time you read this document. That's why I have used the <EM>x.x.x</EM> convention, instead of using hardcoded version numbers. Remember to replace
  +the <EM>x.xx</EM> place-holders with the version numbers of the distributions you are about
  +to use. To find out the latest stable version number, visit the components'
   sites. So if I say <A
   HREF="http://perl.apache.org/dist/mod_perl-x.xx.tar.gz">http://perl.apache.org/dist/mod_perl-x.xx.tar.gz</A>
   , go to <A
   HREF="http://perl.apache.org/dist/">http://perl.apache.org/dist/</A> in
  -order to learn the version number.
  +order to learn the version number of the latest stable release and download
  +the appropriate file.
   
   <P>
  -Unless told different, all the components install themselves into a default
  -location. When you run <CODE>make install</CODE> the installation program tells you where it's going to install the files.
  +Unless otherwise noted, all the components install themselves into a
  +default location. When you run <CODE>make install</CODE> the installation program tells you where it's going to install the files.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -1402,10 +1463,10 @@
   Un-pack:
   
   <P>
  -<PRE>  % tar zvxf mod_perl-x.xx
  -  % tar zvxf apache_x.x.x.tar.gz
  -  % tar zvxf mod_ssl-x.x.x-x.x.x.tar.gz
  -  % tar zvxf openssl-x.x.x.tar.gz
  +<PRE>  % tar xvzf mod_perl-x.xx
  +  % tar xvzf apache_x.x.x.tar.gz
  +  % tar xvzf mod_ssl-x.x.x-x.x.x.tar.gz
  +  % tar xvzf openssl-x.x.x.tar.gz
   </PRE>
   <P>
   Configure, build and install openssl:
  @@ -1429,6 +1490,10 @@
           APACI_ARGS=--enable-module=ssl,--enable-module=rewrite
   </PRE>
   <P>
  +Note: Do not forget that if you use <CODE>csh</CODE> or <CODE>tcsh</CODE> you may need to put all the arguments to `perl Makefile.PL' on a single
  +command line.
  +
  +<P>
   Build, test and install:
   
   <P>
  @@ -1438,11 +1503,11 @@
     % make install
   </PRE>
   <P>
  -Now proceed with mod_ssl and mod_perl parts of the server configurations,
  +Now proceed with the mod_ssl and mod_perl parts of the server configuration
   before starting the server.
   
   <P>
  -When the server started you should see the following or alike in the
  +When the server starts you should see the following or similar in the
   <EM>error_log</EM> file:
   
   <P>
  @@ -1454,12 +1519,11 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="mod_perl_and_mod_ssl_Rolled_from">mod_perl and mod_ssl Rolled from RPMs</A></H2></CENTER>
   <P>
  -Just as in previous section this one shows an installation of mod_perl and
  -mod_sll, but this time using a with all the sources/binaries coming
  -prepackaged in RPMs.
  +As in the previous section this shows an installation of mod_perl and
  +mod_ssl, but this time using sources/binaries prepackaged in RPMs.
   
   <P>
  -(As always replace xxx with proper version numbers. And <CODE>i386</CODE> with your platform if different from x86.)
  +As always, replace <EM>xxx</EM> with the proper version numbers. And replace <CODE>i386</CODE> with the identifier for your platform if it is different.
   
   <OL>
   <P><LI>
  @@ -1527,7 +1591,7 @@
        DO_HTTPD=1 \
        USE_APACI=1 \
        PREP_HTTPD=1 \
  -     EVERYTHING=1 \
  +     EVERYTHING=1
   </PRE>
   <P>
   Add or remove parameters if appropriate.
  @@ -1582,7 +1646,7 @@
   <PRE>  % make certificate 
   </PRE>
   <P>
  -with whatever option is suitable to your config.
  +with whatever option is suitable to your configuration.
   
   <P><LI>
   <P>
  @@ -1593,23 +1657,26 @@
   You should be all set.
   
   <P>
  -Note: If you use the standard config for mod_ssl don't forget to run apache
  -as : ``<CODE>httpd -DSSL</CODE>''
  +Note: If you use the standard config for mod_ssl don't forget to run Apache
  +like this:
   
   <P>
  +<PRE>  % httpd -DSSL
  +</PRE>
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="mod_perl_and_apache_ssl_openss">mod_perl and apache-ssl (+openssl)</A></H2></CENTER>
   <P>
   Apache-SSL is a secure Webserver, based on Apache and SSLeay/OpenSSL. It is
  -licensed under a BSD-style license, which means, in short, that you are
  -free to use it for commercial or non-commercial purposes, so long as you
  -retain the copyright notices.
  +licensed under a BSD-style license which means, in short, that you are free
  +to use it for commercial or non-commercial purposes, so long as you retain
  +the copyright notices.
   
   <P>
   Download the sources:
   
   <P>
  -<PRE>  % lwp-download <A HREF="http://www.apache.org/dist/apache_x.xx.tar.gz">http://www.apache.org/dist/apache_x.xx.tar.gz</A>
  +<PRE>  % lwp-download <A HREF="http://www.apache.org/dist/apache_x.x.x.tar.gz">http://www.apache.org/dist/apache_x.x.x.tar.gz</A>
     % lwp-download <A HREF="http://perl.apache.org/dist/mod_perl-x.xx.tar.gz">http://perl.apache.org/dist/mod_perl-x.xx.tar.gz</A>
     % lwp-download <A HREF="http://www.apache-ssl.org/.../apache_x.x.x+ssl_x.xx.tar.gz">http://www.apache-ssl.org/.../apache_x.x.x+ssl_x.xx.tar.gz</A>
     % lwp-download <A HREF="http://www.openssl.org/source/openssl-x.x.x.tar.gz">http://www.openssl.org/source/openssl-x.x.x.tar.gz</A>
  @@ -1618,9 +1685,9 @@
   Un-pack:
   
   <P>
  -<PRE>  % tar zvxf mod_perl-x.xx
  -  % tar zvxf apache_x.x.x.tar.gz
  -  % tar zvxf openssl-x.x.x.tar.gz
  +<PRE>  % tar xvzf mod_perl-x.xx
  +  % tar xvzf apache_x.x.x.tar.gz
  +  % tar xvzf openssl-x.x.x.tar.gz
   </PRE>
   <P>
   Configure and install openssl:
  @@ -1635,22 +1702,18 @@
   
   <P>
   <PRE>  % cd apache_x.xx
  -  % tar -zxf ../apache_x.x.x+ssl_x.xx.tar.gz
  +  % tar xzvf ../apache_x.x.x+ssl_x.xx.tar.gz
     % FixPatch
     Do you want me to apply the fixed-up Apache-SSL patch for you? [n] y
   </PRE>
  -<P>
  -<PRE>  % &lt;edit the src/Configuration file if needed&gt;
  -  % cd -
  -</PRE>
   <P>
  -Configure:
  +Now edit the <EM>src/Configuration</EM> file if needed and then configure:
   
   <P>
   <PRE>  % cd ../mod_perl-x.xx
     % perl Makefile.PL USE_APACI=1 EVERYTHING=1 \
           DO_HTTPD=1 SSL_BASE=/usr/local/ssl \
  -        APACHE_SRC=../apache_x.x.x/src \
  +        APACHE_SRC=../apache_x.x.x/src
   </PRE>
   <P>
   Build, test and install:
  @@ -1662,12 +1725,12 @@
     % make install
   </PRE>
   <P>
  -Note, that you might need to modify the 'make test' stage, as it takes much
  -longer for this server to get started and <CODE>make test</CODE> waits only a few seconds before it timeouts.
  +Note that you might need to modify the 'make test' stage, as it takes much
  +longer for this server to get started and <CODE>make test</CODE> waits only a few seconds for Apache to start before it times out.
   
   <P>
  -Now proceed with apache_ssl and mod_perl parts of the server configuration
  -files, before starting the server.
  +Now proceed with configuration of the apache_ssl and mod_perl parts of the
  +server configuration files, before starting the server.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -1678,25 +1741,25 @@
   
   <P>
   You must first build and install Stronghold without mod_perl, following
  -Stronghold's install procedure. For more information visit: <A
  +Stronghold's install procedure. For more information visit <A
   HREF="http://www.c2.net/products/sh2/">http://www.c2.net/products/sh2/</A>
   .
   
   <P>
  -Download the sources:
  +Having done that, download the sources:
   
   <P>
   <PRE>  % lwp-download <A HREF="http://perl.apache.org/dist/mod_perl-x.xx.tar.gz">http://perl.apache.org/dist/mod_perl-x.xx.tar.gz</A>
   </PRE>
   <P>
  -Un-pack:
  +Unpack:
   
   <P>
  -<PRE>  % tar zvxf mod_perl-x.xx.tar.gz
  +<PRE>  % tar xvzf mod_perl-x.xx.tar.gz
   </PRE>
   <P>
   Configure (assuming that you have the Stronghold sources extracted at
  -<EM>/usr/local/stronghold</EM>:
  +<EM>/usr/local/stronghold</EM>):
   
   <P>
   <PRE>  % cd mod_perl-x.xx
  @@ -1712,7 +1775,8 @@
   <P>
   Before running <CODE>make test</CODE>, you must add your <CODE>StrongholdKey</CODE> to
   <EM>t/conf/httpd.conf</EM>. If you are configuring by hand, be sure to edit
  -<EM>src/modules/perl/Makefile</EM> and uncomment <CODE>#APACHE_SSL</CODE> directive.
  +<EM>src/modules/perl/Makefile</EM> and uncomment the <CODE>#APACHE_SSL</CODE>
  +directive.
   
   <P>
   Test and Install:
  @@ -1726,34 +1790,32 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H3><A NAME="Note_For_Solaris_2_5_users">Note For Solaris 2.5 users</A></H3></CENTER>
   <P>
  -There has been a report related to the <CODE>REGEX</CODE> that comes with Stronghold, after building Apache with mod_perl would
  -produce core dumps. To get around this:
  +There has been a report related to the <CODE>REGEX</CODE> library that comes with Stronghold, that after building Apache with
  +mod_perl it would produce core dumps. To work around this problem, in
  +<EM>$STRONGHOLD/src/Configuration</EM> change:
   
   <P>
  -In <EM>$STRONGHOLD/src/Configuration</EM>, Change:
  -
  -<P>
   <PRE>  Rule WANTHSREGEX=default
   </PRE>
   <P>
  -To:
  +to:
   
   <P>
   <PRE>  Rule WANTHSREGEX=no
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="mod_perl_Installation_with_CPAN_">mod_perl Installation with CPAN.pm's Interactive Shell</A></H1></CENTER>
  +<CENTER><H1><A NAME="mod_perl_Installation_with_the_C">mod_perl Installation with the CPAN.pm Interactive Shell</A></H1></CENTER>
   <P>
  -To install mod_perl and all the required packages is much easier with help
  -of <CODE>CPAN.pm</CODE> module, which provides you among other features a shell interface to a CPAN
  -repository (CPAN = Comprehensive Perl Archive Network, which is a
  -repository of thousands Perl modules, scripts and documentation. See <A
  -HREF="http://cpan.org">http://cpan.org</A> for more info)
  +Installation of mod_perl and all the required packages is much easier with
  +help of the <CODE>CPAN.pm</CODE> module, which provides you among other features with a shell interface to
  +the CPAN repository. CPAN is the Comprehensive Perl Archive Network, a
  +repository of thousands of Perl modules, scripts and documentation. See <A
  +HREF="http://cpan.org">http://cpan.org</A> for more information.
   
   <P>
  -First thing first is to download an Apache source code, unpack it into a
  -directory the name of which you will need very soon. 
  +The first thing first is to download the Apache source code and unpack it
  +into a directory -- the name of which you will need very soon.
   
   <P>
   Now execute:
  @@ -1762,24 +1824,32 @@
   <PRE>  % perl -MCPAN -eshell
   </PRE>
   <P>
  -If it's a first time that you use it, it will ask you about 10 questions to
  -configure the module. It's quite easy to accomplish this task, when
  -following the very helpful hints coming along with the questions. When you
  -done, you will see a <CODE>cpan</CODE> prompt:
  +If it's the first time that you have used it, <CODE>CPAN.pm</CODE> will ask you about a dozen questions to configure the module. It's quite
  +easy to accomplish this task, and very helpful hints come along with the
  +questions. When you are finished you will see the <CODE>CPAN</CODE> prompt:
   
   <P>
   <PRE>  cpan&gt; 
   </PRE>
  +<P>
  +It can be a good idea to install a special <CODE>CPAN</CODE> bundle of modules to make the use easier. The installation is as simple as
  +typing:
  +
  +<P>
  +<PRE>  cpan&gt; install Bundle::CPAN
  +</PRE>
   <P>
  -CPAN will download mod_perl for you, unpack it, will check prerequisites,
  -detect the missing third party modules if any, download and install them.
  -All you need to install mod_perl is to type at the prompt:
  +The <CODE>CPAN</CODE> shell will download mod_perl for you, unpack it, check for the
  +prerequisites, detect any missing third party modules, and download and
  +install them. All you need to do to install mod_perl is to type at the
  +prompt:
   
   <P>
   <PRE>  cpan&gt; install mod_perl
   </PRE>
   <P>
  -You will see (I'll use <CODE>x.xx</CODE> instead of real version numbers, since these change very frequently):
  +You will see (I'll use <CODE>x.xx</CODE> as a placeholder for real version numbers, since these change very
  +frequently):
   
   <P>
   <PRE>  Running make for DOUGM/mod_perl-x.xx.tar.gz
  @@ -1790,18 +1860,19 @@
     
     Enter `q' to stop search
     Please tell me where I can find your apache src
  -  [../apache-x.x.x/src]
  +  [../apache_x.x.x/src]
   </PRE>
   <P>
  -It will search for a latest apache sources and suggest a directory. Here
  -you need to type in the directory you have unpacked the apache in unless it
  -CPAN detected and suggested the right directory... The next question is
  -about the <CODE>src</CODE> directory which resides at the root level of the unpacked Apache
  -distribution. In most cases CPAN would ``guess'' the correct directory.
  +<CODE>CPAN.pm</CODE> will search for the latest Apache sources and suggest a directory. Here,
  +unless the CPAN shell found it and suggested the right directory, you need
  +to type the directory into which you unpacked Apache. The next question is
  +about the <CODE>src</CODE> directory, which resides at the root level of the unpacked Apache
  +distribution. In most cases the CPAN shell will suggest the correct
  +directory.
   
   <P>
   <PRE>  Please tell me where I can find your apache src
  -  [../apache-x.x.x/src] 
  +  [../apache_x.x.x/src] 
   </PRE>
   <P>
   Answer yes to all the following questions, unless you have a reason not to
  @@ -1812,85 +1883,84 @@
     Shall I build httpd in /usr/src/apache_x.x.x/src for you? [y] 
   </PRE>
   <P>
  -Now it will build the apache with enabled mod_perl. The only thing left to
  -do is to go to apache sources root directory (when you quit
  -<CODE>CPAN</CODE> shell or use using another terminal) and run:
  +Now we will build Apache with mod_perl enabled. Quit the <CODE>CPAN</CODE>
  +shell, or use use another terminal. Go to the Apache sources root directory
  +and run:
   
   <P>
   <PRE>  % make install
   </PRE>
   <P>
   which will complete the installation by installing Apache headers and the
  -binary at the appropriate directories.
  +binary in the appropriate directories.
   
   <P>
  -The only caveat of described process is that you don't have a control over
  -a configuration process. Actually, it's an easy to solve problem -- you can
  -tell &lt;CPAN.pm&gt; to pass whatever parameters you want to
  -<CODE>perl Makefile.PL</CODE>. You do this with <CODE>o conf makepl_arg</CODE> command:
  +The only caveat of described process is that you don't have control over
  +the configuration process. Actually, that problem is easy to solve -- you
  +can tell &lt;CPAN.pm&gt; to pass whatever parameters you want to <CODE>perl Makefile.PL</CODE>. You do this with <CODE>o conf makepl_arg</CODE>
  +command:
   
   <P>
   <PRE>  cpan&gt; o conf makepl_arg 'DO_HTTPD=1 USE_APACI=1 EVERYTHING=1'
   </PRE>
   <P>
  -You just enlist all the parameters like you were to pass to a familiar
  -<CODE>perl Makefile.PL</CODE>. If you add
  -<CODE>APACHE_SRC=/usr/src/apache_x.x.x/src</CODE> and <CODE>DO_HTTPD=1</CODE> parameters, you will be not asked a single question. Of course use a
  -correct path to the apache source distribution.
  +Just list all the parameters like you were to pass to the familiar
  +<CODE>perl Makefile.PL</CODE>. If you add the
  +<CODE>APACHE_SRC=/usr/src/apache_x.x.x/src</CODE> and <CODE>DO_HTTPD=1</CODE> parameters, you will be not asked a single question. Of course you must
  +give the correct path to the Apache source distribution.
   
   <P>
  -Now proceed with <CODE>install mod_perl</CODE>, like before. When the installation is completed, remember to unset the <CODE>makepl_arg</CODE>
  -variable, by executing:
  +Now proceed with <CODE>install mod_perl</CODE> as before. When the installation is completed, remember to unset the <CODE>makepl_arg</CODE> variable by executing:
   
   <P>
   <PRE>  cpan&gt; o conf makepl_arg ''
   </PRE>
   <P>
  -In case you have the <CODE>makepl_arg</CODE> previously (before you altered it for a mod_perl installation) set to some
  -value, you will probably want to save it somewhere, and restore when you
  -done with mod_perl installation. To read the original value, use:
  +If you have previously set <CODE>makepl_arg</CODE> to some value, before you alter it for the mod_perl installation you will
  +probably want to save it somewhere so that you can restore it when you are
  +done with the mod_perl installation. To see the original value, use:
   
   <P>
   <PRE>  cpan&gt; o conf makepl_arg
   </PRE>
   <P>
  -You can install all the modules you might want to use with mod_perl. You
  -install them all by typing a singe command:
  +You can now install all the modules you might want to use with mod_perl.
  +You install them all by typing a singe command:
   
   <P>
   <PRE>  cpan&gt; install Bundle::Apache
   </PRE>
   <P>
  -It'll install mod_perl if isn't yet installed and many other packages like: <CODE>ExtUtils::Embed</CODE>, <CODE>MIME::Base64</CODE>, <CODE>URI::URL</CODE>,
  +This will install mod_perl if isn't yet installed, and many other packages
  +such as: <CODE>ExtUtils::Embed</CODE>, <CODE>MIME::Base64</CODE>, <CODE>URI::URL</CODE>,
   <CODE>Digest::MD5</CODE>, <CODE>Net::FTP</CODE>, <CODE>LWP</CODE>, <CODE>HTML::TreeBuilder</CODE>, <CODE>CGI</CODE>,
   <CODE>Devel::Symdump</CODE>, <CODE>Apache::DB</CODE>, <CODE>Tie::IxHash</CODE>, <CODE>Data::Dumper</CODE> and etc.
   
   <P>
  -A helpful hint: If you have a system with all the perl modules you use and
  +A helpful hint: If you have a system with all the Perl modules you use and
   you want to replicate them all at some other place, and if you cannot just
   copy the whole <CODE>/usr/lib/perl5</CODE> directory because of a possible binary incompatibility of the other system,
  -making your own bundle comes as a handy solution. To accomplish that the
  -command
  +making your own bundle is a handy solution. To accomplish that the command
   <CODE>autobundle</CODE> can be used on the CPAN shell command line. This command writes a bundle
   definition file for all modules that are installed for the currently
   running perl interpreter.
   
   <P>
  -With a clever bundle file you can then simply say
  +With the clever bundle file you can then simply say
   
   <P>
   <PRE>  cpan&gt; install Bundle::my_bundle
   </PRE>
   <P>
  -then answer a few questions and then go out for a coffee.
  +and after answering a few questions, go out for a coffee.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Installing_on_multiple_machines">Installing on multiple machines</A></H1></CENTER>
   <P>
   You may wish to build httpd once, then copy it to other machines. The Perl
  -side of mod_perl needs the apache headers files to compile, to avoid
  -dragging and build apache on all your other machines, there are a few
  +side of mod_perl needs the Apache headers files to compile. To avoid
  +dragging and build Apache on all your other machines, there are a few
   Makefile targets to help you out:
   
   <P>
  @@ -1898,42 +1968,44 @@
   </PRE>
   <P>
   This will tar all files mod_perl installs in your Perl's <EM>site_perl</EM>
  -directory, into a file called <EM>Apache.tar</EM>. You can then unpack this under <EM>site_perl</EM> directory on another machine.
  +directory, into a file called <EM>Apache.tar</EM>. You can then unpack this under the <EM>site_perl</EM> directory on another machine.
   
   <P>
   <PRE>  % make offsite-tar
   </PRE>
   <P>
  -This will copy all header files from the apache source directory you
  -configured mod_perl against, then it will <CODE>make dist</CODE> which creates a mod_perl-x.xx.tar.gz, ready to unpack on another machine to
  +This will copy all the header files from the Apache source directory which
  +you configured mod_perl against, then it will <CODE>make dist</CODE> which creates a mod_perl-x.xx.tar.gz, ready to unpack on another machine to
   compile and install the Perl side of mod_perl.
   
   <P>
   If you really want to make your life easy you should use one of the more
   advanced packaging systems. For example, almost all Linux OS distributions
  -use packaging tools on top of plain tar.gz, allowing to track prerequisites
  -for each package, easy installation, upgrade and cleanup. Once of the most
  -used packagers is RPM (Red Hat Package Manager) See <A
  -HREF="http://www.rpm.org">http://www.rpm.org</A> for more information.
  -
  -<P>
  -So what you have to do is to prepare a SRPM (source distribution package),
  -then build a binary release, which then can be installed on any number of
  -machines in a matter of seconds. 
  -
  -<P>
  -It would work even on live machines! If you have two identical machines
  -(both software and hardware, hardware is less critical, depending on your
  -setup). One is a live server and the other -- development, if you build an
  -RPM with mod_perl binary distribution, install it on the development
  -machine and find it working and stable. You can install the RPM package on
  -the live server without any fear. Just make sure that the <EM>httpd.conf</EM> is correct, since it generally includes parameters unique to the live
  -machine, like hostname.
  -
  -<P>
  -When you installed the package just restart the server. It can be a good
  -idea to keep the previous package of the system, so in case something is
  -going wrong you can remove the installed package and put the old once back.
  +use packaging tools on top of plain tar.gz, allowing you to track
  +prerequisites for each package, and providing easy installation, upgrade
  +and cleanup. One of the most well-used packagers is RPM (Red Hat Package
  +Manager). See <A HREF="http://www.rpm.org">http://www.rpm.org</A> for more
  +information.
  +
  +<P>
  +All you have to do is prepare a SRPM (source distribution package), then
  +build a binary release. This can be installed on any number of machines in
  +a matter of seconds.
  +
  +<P>
  +It will even work on live machines! If you have two identical machines
  +(identical software and hardware, although depending on your setup hardware
  +is less critical). Let's say that one is a live server and the other is in
  +development. You build an RPM with a mod_perl binary distribution, install
  +it on the development machine and find it working and stable. You can
  +install the RPM package on the live server without any fear. Make sure that <EM>httpd.conf</EM> is correct, since it generally includes parameters such as hostname which
  +are unique to the live machine.
  +
  +<P>
  +When you have installed the package, just restart the server. It can be a
  +good idea to keep a package of the previous system, in case something goes
  +wrong. You can then easily remove the installed package and put the old one
  +back.
   
   <P>
   (META: Do you care to share a step by step scenario of preparation of SRPMs
  @@ -1943,19 +2015,19 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="using_RPM_DEB_and_other_package">using RPM, DEB and other packages to install mod_perl</A></H1></CENTER>
   <P>
  -META: meanwhile only RPM. please submit the info about DEB and other
  -available packages.
  +META: Currently only RPM. Please submit info about DEB and other available
  +packages.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Static_debian_package">Static debian package</A></H2></CENTER>
   <P>
  -David Huggins-Daines has built a static apache/mod_perl 1.3.9/1.21 debian
  +David Huggins-Daines has built a static Apache/mod_perl 1.3.9/1.21 Debian
   package.
   
   <P>
  -David has hacked the Debian package to build with static mod_perl in the
  -Apache binary, source and binary packages are at:
  +David has hacked the Debian package to build the Apache binary, with static
  +mod_perl. Source and binary packages are at:
   
   <P>
   <A
  @@ -1963,37 +2035,36 @@
   
   
   <P>
  -Or put this in your <EM>/etc/apt/sources.list</EM> and ``apt-get install apache-perl'':
  +Or put this in your <EM>/etc/apt/sources.list</EM> and run <CODE>&quot;apt-get
  +install apache-perl&quot;</CODE>:
   
   <P>
   <PRE>  % deb <A HREF="http://elgin.plcom.on.ca/debian">http://elgin.plcom.on.ca/debian</A> unstable main
   </PRE>
   <P>
  -(note: this server may be up and down for a bit, it's also the development
  -machine for David's project at work that uses mod_perl...)
  +Note: this server may be up and down for a bit, it's also the development
  +machine for David's project at work that uses mod_perl...
   
   <P>
  -These aren't official packages, of course. Hopefully the memory leakage on
  -DSO problem can be resolved before we release potato, it is a rather severe
  -bug IMHO.
  +These aren't official debian packages, of course.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="A_word_on_mod_perl_RPM_packages">A word on mod_perl RPM packages</A></H2></CENTER>
   <P>
  -The virtues of RPM packages is the subject of much debate among mod_perl
  +The virtues of RPM packages is a subject of much debate among mod_perl
   users. While RPMs do take the pain away from package installation and
   maintenance for most applications, the nuances of mod_perl make RPMs
   somewhat less than ideal for those just getting started. The following help
   and advice is for those new to mod_perl, Apache, Linux, and RPMs. If you
  -know what you are doing, this is probably old hat - contributing your past
  -experiences is, as always, welcome by the community.
  +know what you are doing, this is probably Old Hat - contributing your past
  +experiences is, as always, welcomed by the community.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Getting_Started">Getting Started</A></H2></CENTER>
   <P>
  -If you are new to mod_perl and are using this Guide and the Eagle book to
  +If you are new to mod_perl and are using this Guide and the Eagle Book to
   help you on your way, it is probably better to grab the latest Apache and
   mod_perl sources and compile the sources yourself. Not only will you find
   that this is less daunting than you suspect, but it will probably save you
  @@ -2007,14 +2078,14 @@
   want to play with.
   
   <P>
  -It is also unlikely that the file system's layout of an RPM package will
  -match what you see in either the Eagle book or this Guide. If you are new
  -to mod_perl, Apache, or both, you will probably want to get familiar with
  -file system used by the examples given here before trying something less
  -standard.
  +It is also unlikely that the file system layout of an RPM package will
  +match what you see in the Eagle Book and this Guide. If you are new to
  +mod_perl, Apache, or both you will probably want to get familiar with the
  +file system layout used by the examples given here before trying something
  +less standard.
   
   <P>
  -Finally, the RPMs found on a typical distribution CDs use mod_perl build
  +Finally, the RPMs found on a typical distribution CDs use mod_perl built
   with Apache's Dynamic Shared Objects (<CODE>DSO</CODE>) support. While mod_perl can be successfully used as a DSO module, it adds
   a layer of complexity that you may want to live without for now.
   
  @@ -2026,7 +2097,7 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Compiling_RPM_source_files">Compiling RPM source files</A></H2></CENTER>
   <P>
  -It is possible to compile the source files provided my RPM packages, but if
  +It is possible to compile the source files provided by RPM packages, but if
   you are using RPMs to ease mod_perl installation, that is not the way to do
   it. Both Apache and mod_perl RPMs are designed to be install-and-go. If you
   really want to compile mod_perl to your own specific needs, your best bet
  @@ -2044,14 +2115,14 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Installing_a_single_apache_mod_p">Installing a single apache+mod_perl RPM</A></H2></CENTER>
   <P>
  -If you use an apache+mod_perl RPM, chances are <CODE>rpm -i</CODE> or <CODE>glint</CODE>
  +If you use an Apache+mod_perl RPM, chances are <CODE>rpm -i</CODE> or <CODE>glint</CODE>
   (GUI for RPM) will have you up and running immediately, no compilation
   necessary. If you encounter problems, try downloading from another mirror
   site or searching <A HREF="http://rpmfind.net/">http://rpmfind.net/</A> for
  -a different package - there are plenty out there to choose from. 
  +a different package - there are plenty out there to choose from.
   
   <P>
  -David Harris has started the efforts to build a better RPM/SRPM mod_perl
  +David Harris has started an effort to build better RPM/SRPM mod_perl
   packages. You will find them at: <A
   HREF="http://www.davideous.com/modperlrpm/distrib/">http://www.davideous.com/modperlrpm/distrib/</A>
   
  @@ -2077,7 +2148,7 @@
   
   <P><LI>
   <P>
  -Checks the module magic number on the existing apache package to see if
  +Checks the module magic number on the existing Apache package to see if
   things are compatible
   
   </UL>
  @@ -2097,17 +2168,17 @@
     /usr/sbin/httpd_modperl
   </PRE>
   <P>
  -This package does not install a complete apache subtree built with
  +This package does not install a complete Apache subtree built with
   mod_perl, but rather just the two above files that are different for
   mod_perl. This conceptually thinks of mod_perl as a kind of an ``add on''
  -that we would like to add to the regular apache tree. However, we are
  +that we would like to add to the regular Apache tree. However, we are
   prevented from distributing mod_perl as an actual DSO, because it is not
   recommended by the mod_perl developers and various features must be turned
  -off. So, instead, we distribute a httpd binary with mod_perl statically
  +off. So, instead, we distribute an httpd binary with mod_perl statically
   linked (httpd_modperl) and the special modified mod_include.so required for
   this binary (mod_include_modperl.so). You can use the exact same
   configuration files and other DSO modules, but you just ``enable'' the
  -mod_perl ``add on'' by following the below directions.
  +mod_perl ``add on'' by following the directions below.
   
   <P>
   To enable mod_perl, do the following:
  @@ -2120,21 +2191,29 @@
     (3) Uncomment the &quot;AddModule mod_perl.c&quot; line in /etc/httpd/conf/httpd.conf
   </PRE>
   <P>
  -Or run the following command: (and the other version to disable mod_perl)
  +Or run the following command:
   
   <P>
   <PRE>  /usr/sbin/modperl-enable on
  -  /usr/sbin/modperl-enable off
   </PRE>
   <P>
  +and to disable mod_perl:
  +
  +<P>
  +<PRE>  /usr/sbin/modperl-enable off
  +</PRE>
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Compiling_libapreq_Apache_Requ">Compiling libapreq (Apache::Request) with the RH 6.0 mod_perl RPM</A></H2></CENTER>
   <P>
  -There have been many reports of libapreq - which provides the
  -<CODE>Apache::Request</CODE> module - not working properly with various RPM packages. However, it is
  -possible to integrate libapreq with mod_perl RPMs, it just requires a few
  -additional steps.
  +Libapreq provides the <A HREF="././download.html#Apache_Request">Apache::Request</A>
  +module.
   
  +<P>
  +Despite many reports of libapreq not working properly with various RPM
  +packages, it is possible to integrate libapreq with mod_perl RPMs. It just
  +requires a few additional steps.
  +
   <OL>
   <P><LI>
   <P>
  @@ -2143,22 +2222,23 @@
   <P><LI>
   <P>
   Install the source RPM for your mod_perl RPM and then do a build prep,
  -which unpacks the sources. From there, copy four header files (<EM>mod_perl.h</EM>, <EM>mod_perl_version.h</EM>, <EM>mod_perl_xs.h</EM>, and
  -<EM>mod_PL.h</EM>) to <CODE>/usr/include/apache</CODE>.
  +(with <CODE>rpm -bp apache-devel-x.x.x-x.src.rpm</CODE>) which unpacks the sources. From there, copy the four header files (<EM>mod_perl.h</EM>,
  +<EM>mod_perl_version.h</EM>, <EM>mod_perl_xs.h</EM>, and <EM>mod_PL.h</EM>) to
  +<CODE>/usr/include/apache</CODE>.
   
   <UL>
   <P><LI>
   <P>
   2.1 Get the SRPM from
  -<CODE>somemirror.../redhat-6.0/SRPMS/mod_perl-1.19-2.src.rpm</CODE>.
  +<CODE>somemirror.../redhat-x.x/SRPMS/mod_perl-x.xx-x.src.rpm</CODE>.
   
   <P><LI>
   <P>
  -2.2 Install the SRPM. (This creates files in <CODE>/usr/src/redhat/SPECS</CODE>
  -and <CODE>/usr/src/redhat/SOURCES</CODE>). Run:
  +2.2 Install the SRPM. This creates files in <CODE>/usr/src/redhat/SPECS</CODE>
  +and <CODE>/usr/src/redhat/SOURCES</CODE>. Run:
   
   <P>
  -<PRE> % rpm -ih mod_perl-1.19-2.src.rpm
  +<PRE> % rpm -ih mod_perl-x.xx-x.src.rpm
   </PRE>
   <P><LI>
   <P>
  @@ -2190,15 +2270,13 @@
     + exit 0
   </PRE>
   <P>
  -NOTE: What you have just done in steps 2.1 through 2.3 was just a fancy
  -un-packing of the source tree that builds the RPM into
  -<CODE>/usr/src/redhat/BUILD/mod_perl-1.19</CODE>. You could un-pack the
  -<CODE>mod_perl-x.xx.tar.gz</CODE> file somewhere and then do the following steps on that source tree. But
  -this is more ``pure'' because I'm grabbing the header files from the same
  -tree that built the RPM. But this does not matter because RedHat is not
  -patching that file. So, it might be better if you just tell the person to
  -grab the mod_perl source and unpack it to get these files.. less fuss and
  -mess.
  +NOTE: Steps 2.1 through 2.3 are just a fancy un-packing of the source tree
  +that builds the RPM into <CODE>/usr/src/redhat/BUILD/mod_perl-x.xx</CODE>. You could unpack the <CODE>mod_perl-x.xx.tar.gz</CODE> file somewhere and then do the following steps on that source tree. The
  +method shown above is more ``pure'' because you're grabbing the header
  +files from the same tree that built the RPM. But this does not matter
  +because RedHat is not patching that file. So, it might be better if you
  +just grab the mod_perl source and unpack it to get these files. Less fuss
  +and mess.
   
   <P><LI>
   <P>
  @@ -2221,7 +2299,7 @@
       -exec cp {} /usr/include/apache \;
   </PRE>
   <P>
  -NOTE: You should not have to do a:
  +NOTE: You should not have to do:
   
   <P>
   <PRE>  % mkdir /usr/include/apache
  @@ -2250,13 +2328,11 @@
   <CENTER><H2><A NAME="Installing_separate_Apache_and_m">Installing separate Apache and mod_perl RPMs</A></H2></CENTER>
   <P>
   If you are trying to install separate Apache and mod_perl RPMs, like those
  -provided by RedHat distributions, you may be in for a bit of a surprise.
  -Installing the Apache RPM will go just fine, and <A
  +provided by the RedHat distributions, you may be in for a bit of a
  +surprise. Installing the Apache RPM will go just fine, and <A
   HREF="http://localhost">http://localhost</A> will bring up some type of web
  -page for your viewing pleasure. However, installation of the mod_perl RPM,
  -followed by the
  -<A HREF="././install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is  running</A>
  -tests, will show that Apache is not mod_perl enabled. This is because
  +page for you. However, after installation of the mod_perl RPM, the <A HREF="././install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A>
  +test will show that Apache is not mod_perl enabled. This is because
   mod_perl needs to be added as a separate module using Apache's Dynamic
   Shared Objects.
   
  @@ -2269,10 +2345,7 @@
     ----------
     LoadModule perl_module modules/libperl.so
     AddModule mod_perl.c
  -</PRE>
  -<P>
  -<PRE>  srm.conf (or httpd.conf in later versions of Apache):
  -  ----------
  +  
     PerlModule Apache::Registry 
     Alias /perl/ /home/httpd/perl/ 
     &lt;Location /perl 
  @@ -2291,8 +2364,7 @@
   <CENTER><H2><A NAME="Testing_the_mod_perl_API">Testing the mod_perl API</A></H2></CENTER>
   <P>
   Some people have reported that even when the server responds positively to
  -the <A HREF="././install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is  running</A>
  -tests, the mod_perl API will not function properly. You may want to run the
  +the <A HREF="././install.html#How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A> tests, the mod_perl API will not function properly. You may want to run the
   below script to verify the availability of the mod_perl API.
   
   <P>
  @@ -2306,52 +2378,52 @@
   <CENTER><H1><A NAME="Installation_Without_Superuser_P">Installation Without Superuser Privileges</A></H1></CENTER>
   <P>
   As you have already learned, mod_perl enabled Apache consists of two main
  -components: perl modules and Apache itself. Let's tackle each task at a
  +components: perl modules and Apache itself. Let's tackle the tasks one at a
   time.
   
   <P>
  -I'll show a complete installation example using a <EM>stas</EM> as a username, and assume that <EM>/home/stas</EM> is a home directory of that user.
  +I'll show a complete installation example using <EM>stas</EM> as a username, assuming that <EM>/home/stas</EM> is the home directory of that user.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Installing_Perl_Modules_into_a_D">Installing Perl Modules into a Directory of Choice</A></H2></CENTER>
   <P>
  -Since without a superuser permissions you aren't allowed to install modules
  -into a system directories like <EM>/usr/lib/perl5</EM>, you need to find out how to install the modules under your home
  -directory. The task is a very one.
  +Since without superuser permissions you aren't allowed to install modules
  +into system directories like <EM>/usr/lib/perl5</EM>, you need to find out how to install the modules under your home
  +directory. It's easy.
   
   <P>
  -First you have to decide where the modules to be installed. The simplest
  -approach is to simulate a relevant to perl portion of the
  -<CODE>/</CODE> file system, under your home directory. Actually we need only two
  -directories:
  +First you have to decide where to install the modules. The simplest
  +approach is to simulate the portion of the <EM>/</EM> file system relevant to Perl under your home directory. Actually we need
  +only two directories:
   
   <P>
   <PRE>  /home/stas/bin
     /home/stas/lib
   </PRE>
   <P>
  -But we don't have to create them, since it'll be done automatically when
  -the first module will be installed. 99% of the files will go into the <EM>lib</EM> directory, occasionally when some module comes with perl scripts, these
  -will go into a <EM>bin</EM> directory, and the directory itself will be created if it wasn't there
  -before.
  +We don't have to create them, since that will be done automatically when
  +the first module is installed. 99% of the files will go into the
  +<EM>lib</EM> directory. Occasionally, when some module distribution comes with Perl
  +scripts, these will go into the <EM>bin</EM> directory. This directory will be created if it doesn't exist.
   
   <P>
  -Let's install a <EM>CGI.pm</EM> package, which among <CODE>CGI.pm</CODE> includes a few other <CODE>CGI::*</CODE> modules. As usually, download the package from CPAN repository, unpack it
  -and <EM>chdir</EM> to the created directory.
  +Let's install the <EM>CGI.pm</EM> package, which includes a few other
  +<CODE>CGI::*</CODE> modules. As usual, download the package from the CPAN repository, unpack it
  +and <CODE>chdir</CODE> to the newly-created directory.
   
   <P>
  -Now we do a standard <CODE>perl Makefile.PL</CODE> to prepare a <EM>Makefile</EM>, but this time we tell the <CODE>MakeMaker</CODE> to use non-default perl installation directories.
  +Now do a standard <CODE>perl Makefile.PL</CODE> to prepare a <EM>Makefile</EM>, but this time tell <CODE>MakeMaker</CODE> to use your Perl installation directories instead of the defaults.
   
   <P>
   <PRE>  % perl Makefile.PL PREFIX=/home/stas
   </PRE>
   <P>
  -<CODE>PREFIX=/home/stas</CODE> is the only different part of the standard perl modules installation
  -process. Note that if you don't like how
  -<CODE>MakeMaker</CODE> choose to select the rest of the directories or if you are using an older
  -version of it, which requires an explicit declaration of all target
  -directories you should do:
  +<CODE>PREFIX=/home/stas</CODE> is the only part of the installation process which is different from usual.
  +Note that if you don't like how
  +<CODE>MakeMaker</CODE> chooses the rest of the directories, or if you are using an older version
  +of it which requires an explicit declaration of all the target directories,
  +you should do this:
   
   <P>
   <PRE>  % perl Makefile.PL PREFIX=/home/stas \
  @@ -2371,9 +2443,9 @@
     % make install
   </PRE>
   <P>
  -We see that <CODE>make install</CODE> installs all the files in my private repository. Note that all the missing
  +<CODE>make install</CODE> installs all the files in the private repository. Note that all the missing
   directories are created automatically, so there is no need to create them
  -in first place. Here is what it does (this is a slightly truncated output):
  +in first place. Here (slightly edited) is what it does :
   
   <P>
   <PRE>  Installing /home/stas/lib/perl5/CGI/Cookie.pm
  @@ -2385,7 +2457,7 @@
   </PRE>
   <P>
   If you have to use the explicit target parameters, instead of a single
  -<CODE>PREFIX</CODE> parameter, you will find it useful to create a file called for example <EM>~/.perl_dirs</EM> (where <EM>~</EM> is <CODE>/home/stas</CODE> in our example) and to populate it with:
  +<CODE>PREFIX</CODE> parameter, you will find it useful to create a file called for example <EM>~/.perl_dirs</EM> (where <EM>~</EM> is <CODE>/home/stas</CODE> in our example) containing:
   
   <P>
   <PRE>    PREFIX=/home/stas \
  @@ -2397,7 +2469,7 @@
       INSTALLMAN3DIR=/home/stas/lib/perl5/man3
   </PRE>
   <P>
  -From now on any time you want to install perl modules locally you simply
  +From now on, any time you want to install perl modules locally you simply
   execute:
   
   <P>
  @@ -2407,9 +2479,9 @@
     % make install
   </PRE>
   <P>
  -Using the last tip, you can easily maintain several Perl module
  -repositories, for example one for production perl and another for
  -development. When the only difference is either you call:
  +Using this method you can easily maintain several Perl module repositories.
  +For example, you could have one for production Perl and another for
  +development:
   
   <P>
   <PRE>  % perl Makefile.PL `cat ~/.perl_dirs.production`
  @@ -2424,15 +2496,15 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Making_Your_Scripts_Find_the_Loc">Making Your Scripts Find the Locally Installed Modules</A></H2></CENTER>
   <P>
  -Perl modules are generally being dispatched into a five main directories.
  -You find out these directories, execute:
  +Perl modules are generally placed in four main directories. To find these
  +directories, execute:
   
   <P>
   <PRE>  % perl -V
   </PRE>
   <P>
  -and in the generated output, among other important information about your
  -perl installation you will see at the end:
  +The output contains important information about your Perl installation. At
  +the end you will see:
   
   <P>
   <PRE>  Characteristics of this binary (from libperl):
  @@ -2445,17 +2517,21 @@
       /usr/lib/perl5/site_perl/5.005
       .
   </PRE>
  +<P>
  +It shows us the content of the Perl special variable <CODE>@INC</CODE>, which is used by Perl to look for its modules. It is equivalent to the <CODE>PATH</CODE>
  +environment variable in Unix shells which is used to find executable
  +programs.
  +
   <P>
  -It shows us the content of the <CODE>@INC</CODE> perl special variable, which is being used by perl to look for its modules,
  -as an equivalent to a
  -<CODE>PATH</CODE> environment variable in Unix shells which is being used to find the
  -binaries to be executed.
  +Notice that Perl looks for modules in the <EM>.</EM> directory too, which stands for the current directory. It's the last entry
  +in the above output.
   
   <P>
  -Of course this is the information of the <EM>5.00503</EM> version of perl installed on my x86 architecture PC running Linux. That's
  -why you see
  -<EM>i386-linux</EM> and <EM>5.00503</EM>. If your system runs a different operating system, processor or chipset
  -architecture and version of perl, directories would have a different names.
  +Of course this example is from version <EM>5.00503</EM> of Perl installed on my x86 architecture PC running Linux. That's why you
  +see
  +<EM>i386-linux</EM> and <EM>5.00503</EM>. If your system runs a different version of Perl, operating system,
  +processor or chipset architecture, then the directories will have different
  +names.
   
   <P>
   I also have a perl-5.00561 installed under <CODE>/usr/local/lib/</CODE>
  @@ -2475,19 +2551,19 @@
       /usr/local/lib/site_perl
   </PRE>
   <P>
  -Notice, that it's still <EM>linux</EM> but a newer perl version uses a version of my Pentium processor (thus the <EM>i586</EM> and not <EM>i386</EM> as it was before), which makes a use of compiler optimization for a Pentium
  -processors, when the binary perl extensions are being created.
  +Note that it's still <EM>Linux</EM>, but the newer Perl version uses the version of my Pentium processor (thus
  +the <EM>i586</EM> and not <EM>i386</EM>). This makes use of compiler optimizations for Pentium processors when the
  +binary Perl extensions are created.
   
   <P>
  -<CODE>i386-linux</CODE> like directories are the ones, where all the platform specific files are
  -supposed to go, such as compiled C files glued to Perl with <CODE>XS</CODE> or <CODE>SWIG</CODE>.
  +All the platform specific files, such as compiled C files glued to Perl
  +with <CODE>XS</CODE> or <CODE>SWIG</CODE>, are supposed to go into <CODE>i386-linux</CODE> like directories.
   
   <P>
  -The above discussion is important to us, because since we have installed
  -the perl modules into a non-standard directories, somehow we have to make
  -Perl know where to look for the four directories. There are two ways to
  -accomplish this task. You should either set the
  -<CODE>PERL5LIB</CODE> environment variable or modify the <CODE>@INC</CODE> variable in yours scripts.
  +Important: As we have installed the Perl modules into non-standard
  +directories, we have to let Perl know where to look for the four
  +directories. There are two ways to accomplish this. You can either set the <CODE>PERL5LIB</CODE> environment variable, or you can modify the
  +<CODE>@INC</CODE> variable in your scripts.
   
   <P>
   Assuming that we use perl-5.00503, in our example the directories are:
  @@ -2499,21 +2575,21 @@
       /home/sbekman/lib/perl5/site_perl/5.005
   </PRE>
   <P>
  -As I've mentioned it before, you find out the exact directories by
  -executing <CODE>perl -V</CODE> and replacing the global's perl installation's base directory with your
  -home directory.
  +As mentioned before, you find the exact directories by executing
  +<CODE>perl -V</CODE> and replacing the global Perl installation's base directory with your home
  +directory.
   
   <P>
  -Modifying <CODE>@INC</CODE> is quite easy. The best approach is to use <CODE>lib</CODE>
  -module, by adding the following snippet at the top of all your scripts that
  -require the locally installed modules.
  +Modifying <CODE>@INC</CODE> is quite easy. The best approach is to use the
  +<CODE>lib</CODE> module (pragma), by adding the following snippet at the top of any of your
  +scripts that require the locally installed modules.
   
   <P>
   <PRE>  use lib qw(/home/stas/lib/perl5/5.00503/
                /home/stas/lib/perl5/site_perl/5.005);
   </PRE>
   <P>
  -Another way is to explicitly write the code to alter <CODE>@INC</CODE>:
  +Another way is to write code to modify <CODE>@INC</CODE> explicitly:
   
   <P>
   <PRE>  BEGIN {
  @@ -2525,51 +2601,46 @@
           }
   </PRE>
   <P>
  -Notice, that with <CODE>lib</CODE> module, we don't have to enlist the corresponding architecture specific
  -directories, since it adds them automatically if they are exist (well, to
  -be exact, when
  -<CODE>$dir/$archname/auto</CODE> directory exists).
  +Note that with the <CODE>lib</CODE> module we don't have to list the corresponding architecture specific
  +directories, since it adds them automatically if they exist (to be exact,
  +when <EM>$dir/$archname/auto</EM>
  +exists).
   
   <P>
  -Also, notice that both approaches prepend the directories to be searched to <CODE>@INC</CODE>, which allows you to install a more recent module into your local
  -repository and perl will use it instead of the older one installed in the
  +Also, notice that both approaches <EM>prepend</EM> the directories to be searched to <CODE>@INC</CODE>. This allows you to install a more recent module into your local
  +repository and Perl will use it instead of the older one installed in the
   main system repository.
   
   <P>
  -Both approaches, modify the value of <CODE>@INC</CODE> at the compilation time,
  -<CODE>lib</CODE> module uses the <EM>BEGIN</EM> block as well, but internally. 
  +Both approaches modify the value of <CODE>@INC</CODE> at compilation time. The
  +<CODE>lib</CODE> module uses the <EM>BEGIN</EM> block as well, but internally.
   
   <P>
   Now, let's assume the following scenario. I have installed <CODE>LWP</CODE>
   package in my local repository. Now I want to install another module (e.g.
  -mod_perl) and it has <CODE>LWP</CODE> listed in its prerequisites list. I know that I've <CODE>LWP</CODE> installed, but when I run <CODE>perl Makefile.PL</CODE>
  -for the module I'm about to install, I'm being told that I don't have
  -<CODE>LWP</CODE> installed.
  +mod_perl) and it has <CODE>LWP</CODE> listed in its prerequisites list. I know that I have <CODE>LWP</CODE> installed, but when I run <CODE>perl Makefile.PL</CODE>
  +for the module I'm about to install I'm told that I don't have <CODE>LWP</CODE>
  +installed.
   
   <P>
  -If we think for a moment, there is no way for Perl to know that we have
  -some locally installed modules. All it does, is searching the directories
  -listed in <CODE>@INC</CODE> and since the latter contains only the default five directories, no wander
  -it cannot find locally installed
  -<CODE>LWP</CODE> package. There is no script we could add the <CODE>@INC</CODE>
  -modification code, but there is a <CODE>PERL5LIB</CODE> variable that I've mentioned before, that solves this problem. If you are
  -using a
  -<CODE>t?csh</CODE> for interactive work, do:
  +There is no way for Perl to know that we have some locally installed
  +modules. All it does is search the directories listed in <CODE>@INC</CODE>, and since the latter contains only the default four directories (plus the
  +<EM>.</EM> directory), it cannot find the locally installed <CODE>LWP</CODE> package. We cannot solve this problem by adding code to modify <CODE>@INC</CODE>, but changing the <CODE>PERL5LIB</CODE> environment variable will do the trick. If you are using <CODE>t?csh</CODE> for interactive work, do this:
   
   <P>
   <PRE>  setenv PERL5LIB /home/stas/lib/perl5/5.00503:
     /home/stas/lib/perl5/site_perl/5.005
   </PRE>
   <P>
  -It should be a single line with directories separated by colons (<CODE>:</CODE>) and no spaces. If you are a <CODE>bash</CODE> user, do:
  +It should be a single line with directories separated by colons (<CODE>:</CODE>) and no spaces. If you are a <CODE>(ba)?sh</CODE> user, do this:
   
   <P>
   <PRE>  export PERL5LIB=/home/stas/lib/perl5/5.00503:
     /home/stas/lib/perl5/site_perl/5.005
   </PRE>
   <P>
  -Again make it a single line. Actually bash allows to have a multi-line
  -settings with help of backslash (<CODE>\</CODE>). So you can set it this way:
  +Again make it a single line. If you use bash you can use multi-line
  +commands by terminating line with a backslash (<CODE>\</CODE>), like this:
   
   <P>
   <PRE>  export PERL5LIB=/home/stas/lib/perl5/5.00503:\
  @@ -2579,8 +2650,8 @@
   As with <CODE>use lib</CODE>, perl automatically prepends the architecture specific directories to <CODE>@INC</CODE> if those exist.
   
   <P>
  -When you have done with this setting, verify the value of the newly
  -configured <CODE>@INC</CODE>, by executing <CODE>perl -V</CODE> as before. Now you should see the modified value of <CODE>@INC</CODE>:
  +When you have done this, verify the value of the newly configured
  +<CODE>@INC</CODE> by executing <CODE>perl -V</CODE> as before. You should see the modified value of <CODE>@INC</CODE>:
   
   <P>
   <PRE>  % perl -V
  @@ -2602,71 +2673,65 @@
       .
   </PRE>
   <P>
  -The moment everything works as you want it to, add this setting into a
  -<EM>.tcshrc</EM> or <EM>.bashrc</EM> file, according to the interactive shell you use, so the next time you open
  -a new shell, this setting would be already in place.
  +When everything works as you want it to, add these commands to your
  +<EM>.tcshrc</EM> or <EM>.bashrc</EM> file. The next time you start a shell, the environment will be ready for
  +you to work with the new Perl.
   
   <P>
  -Note that if you have a <CODE>PERL5LIB</CODE> setting, you don't need to alter the <CODE>@INC</CODE> value in your scripts, only if you are executing them from the interactive
  -shell or in any other way that sets the <CODE>PERL5LIB</CODE>
  -variable. For example, if someone else tries to execute your scripts but
  -doesn't have this setting in the shell she attempts to execute the script
  -from, Perl will fail to find your locally installed modules.
  +Note that if you have a <CODE>PERL5LIB</CODE> setting, you don't need to alter the <CODE>@INC</CODE> value in your scripts. But if for example someone else (who doesn't have
  +this setting in the shell) tries to execute your scripts, Perl will fail to
  +find your locally installed modules. The best example is a crontab script
  +that <EM>might</EM> use a different SHELL environment and therefore the <CODE>PERL5LIB</CODE> setting won't be available to it.
   
   <P>
  -So the best approach is to have both: the <CODE>PERL5LIB</CODE> environment variable and the explicit <CODE>@INC</CODE> extension code at the beginning of the scripts as described before.
  +So the best approach is to have both the <CODE>PERL5LIB</CODE> environment variable and the explicit <CODE>@INC</CODE> extension code at the beginning of the scripts as described above.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="CPAN_pm_Shell_and_Locally_Instal">CPAN.pm Shell and Locally Installed Modules</A></H2></CENTER>
  +<CENTER><H2><A NAME="The_CPAN_pm_Shell_and_Locally_In">The CPAN.pm Shell and Locally Installed Modules</A></H2></CENTER>
   <P>
  -As we saw in the section describing the usage of <CODE>CPAN.pm</CODE> shell to install mod_perl, it saves us a great deal of time, by doing all
  -the job for us, even detecting the missing modules listed in prerequisites,
  -bringing and installing them. So you might wander whether you can use
  -<CODE>CPAN.pm</CODE> to maintain your local repository as well. The answer is yes and I'm going
  -to show how can you make installing modules locally a bliss.
  +As we saw in the section describing the usage of the <CODE>CPAN.pm</CODE> shell to install mod_perl, it saves a great deal of time. It does the job
  +for us, even detecting the missing modules listed in prerequisites,
  +fetching and installing them. So you might wonder whether you can use
  +<CODE>CPAN.pm</CODE> to maintain your local repository as well.
   
   <P>
  -First thing is to configure the CPAN to use our local settings, when you
  -start the <CODE>CPAN</CODE> interactive shell, it searches for configuration files first for <EM>~/.cpan/CPAN/MyConfig.pm</EM> file and then for the the one installed system wide. The two file on my
  -setup are (when I'm logged as user <CODE>stas</CODE>):
  +When you start the <CODE>CPAN</CODE> interactive shell, it searches first for the user's private configuration
  +file and then for the system wide one. When I'm logged as user <CODE>stas</CODE> the two files on my setup are:
   
   <P>
   <PRE>    /home/stas/.cpan/CPAN/MyConfig.pm
       /usr/lib/perl5/5.00503/CPAN/Config.pm
   </PRE>
   <P>
  -If there is no CPAN configured on your system, when you start its shell for
  -the first time, it will ask you a dozen configuration questions and create
  -this file for you. 
  +If there is no the <CODE>CPAN</CODE> shell configured on your system, when you start the shell for the first
  +time it will ask you a dozen configuration questions and then create the <EM>Config.pm</EM> file for you.
   
   <P>
  -In case you've got it already configured, you should have a
  -<CODE>/usr/lib/perl5/5.00503/CPAN/Config.pm</CODE>. If you have a different perl version alter the path to use your perl's
  -version number. Create the directory where the local configuration file
  -will go:
  +If you've got it already system-wide configured, you should have a
  +<CODE>/usr/lib/perl5/5.00503/CPAN/Config.pm</CODE>. If you have a different Perl version, alter the path to use your Perl's
  +version number, when looking up the file. Create the directory (<CODE>mkdir -p</CODE> creates the whole path at once) where the local configuration file will go:
   
   <P>
   <PRE>  % mkdir -p /home/stas/.cpan/CPAN
   </PRE>
   <P>
  -<CODE>mkdir -p</CODE> creates the whole pass at once. Now copy the system wide configuration file
  -to your local one.
  +Now copy the system wide configuration file to your local one.
   
   <P>
   <PRE>  % cp /usr/lib/perl5/5.00503/CPAN/Config.pm /home/stas/.cpan/CPAN/MyConfig.pm
   </PRE>
   <P>
  -The only thing left is to replace the base directory of &lt;.cpan&gt;, to the one under your home, On my machine I replace <CODE>/usr/.cpan</CODE> (that's where my system's <CODE>.cpan</CODE> directory resides) with <CODE>/home/stas</CODE>, using Perl of course!
  +The only thing left is to change the base directory of &lt;.cpan&gt; in your local file to the one under your home directory. On my
  +machine I replace <CODE>/usr/src/.cpan</CODE> (that's where my system's <CODE>.cpan</CODE> directory resides) with <CODE>/home/stas</CODE>. I use Perl of course!
   
   <P>
  -<PRE>  % perl -pi -e 's|/usr/|/home/stas/|' /home/stas/.cpan/CPAN/MyConfig.pm
  +<PRE>  % perl -pi -e 's|/usr/src|/home/stas|' /home/stas/.cpan/CPAN/MyConfig.pm
   </PRE>
   <P>
  -Now when you have the local configuration file ready. either after you
  -created it by hand copying the global <CODE>CPAN/Config.pm</CODE> or by letting
  -<CODE>CPAN.pm</CODE> to create it for you, we have to tell it what special parameters we need to
  -pass when executing <CODE>perl Makefile.PL</CODE> stage.
  +Now you have the local configuration file ready, you have to tell it what
  +special parameters you need to pass when executing the <CODE>perl
  +Makefile.PL</CODE> stage.
   
   <P>
   Open the file in your favorite editor and replace line:
  @@ -2681,21 +2746,22 @@
   <PRE>  'makepl_arg' =&gt; q[PREFIX=/home/stas],
   </PRE>
   <P>
  -And you've finished the configuration. Now start it as usual (assuming that
  -you are logged as the same user you have prepared the local installation
  -for (<EM>stas</EM> in our example):
  +Now you've finished the configuration. Assuming that you are logged as the
  +same user you have prepared the local installation for (<EM>stas</EM>
  +in our example), start it like this:
   
   <P>
   <PRE>  % perl -MCPAN -e shell
   </PRE>
   <P>
  -From now on any module you will try to install will be installed locally.
  -If you need to install some system modules, just become a superuser and
  -install them the same way, this time the global configuration file will be
  -used.
  +From now on any module you try to install will be installed locally. If you
  +need to install some system modules, just become the superuser and install
  +them in the same way. When you are logged in as the superuser, the
  +system-wide configuration file will be used instead of your local one.
   
   <P>
  -If you have used more than just the <CODE>PREFIX</CODE> variable, modify the &lt;MyConfig.pm&gt; to use them, e.g if you have used:
  +If you have used more than just the <CODE>PREFIX</CODE> variable, modify
  +<EM>MyConfig.pm</EM> to use them. For example if you have used these variables:
   
   <P>
   <PRE>    perl Makefile.PL PREFIX=/home/stas \
  @@ -2707,13 +2773,13 @@
       INSTALLMAN3DIR=/home/stas/lib/perl5/man3
   </PRE>
   <P>
  -replace <CODE>PREFIX=/home/stas</CODE> in line:
  +then replace <CODE>PREFIX=/home/stas</CODE> in the line:
   
   <P>
   <PRE>  'makepl_arg' =&gt; q[PREFIX=/home/stas],
   </PRE>
   <P>
  -with all the variables from above:
  +with all the variables from above, so that the line becomes:
   
   <P>
   <PRE>  'makepl_arg' =&gt; q[PREFIX=/home/stas \
  @@ -2732,45 +2798,44 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Making_a_Local_Apache_Installati">Making a Local Apache Installation</A></H2></CENTER>
   <P>
  -Just like with perl modules, when you don't have permissions to install
  -files into a system area, you have to install them locally under your home
  -directory. It's almost the same as a plain installation, but you will have
  -to run the server listening to port number &gt; 1024, since these are the
  -ports only root processes can listen to.
  -
  -<P>
  -Another important issue you would have to solve is how to add an automatic
  -startup and shutdown scripts to the directories use by the rest of the
  -system services. You will have to ask your system administrator to assist
  -you with this issue.
  -
  -<P>
  -Now to install Apache locally, all you have to do is to tell a
  -<CODE>.configure</CODE> script in the Apache source directory what target directories to be used.
  -If following a convention that I use, which makes your home directory
  -looking like the <CODE>/</CODE> (base) directory, the invocation parameters would be:
  +Just like with Perl modules, if you don't have permissions to install files
  +into the system area you have to install them locally under your home
  +directory. It's almost the same as a plain installation, but you have to
  +run the server listening to a port number greater than 1024 since only root
  +processes can listen to lower numbered ports.
  +
  +<P>
  +Another important issue you have to solve is how to add startup and
  +shutdown scripts to the directories used by the rest of the system
  +services. You will have to ask your system administrator to assist you with
  +this issue.
  +
  +<P>
  +To install Apache locally, all you have to do is to tell <CODE>.configure</CODE>
  +in the Apache source directory what target directories to use. If you are
  +following the convention that I use, which makes your home directory look
  +like the <CODE>/</CODE> (base) directory, the invocation parameters would be:
   
   <P>
   <PRE>  ./configure --prefix=/home/stas
   </PRE>
   <P>
   Apache will use the prefix for the rest of its target directories instead
  -of the default <CODE>/usr/local/apache</CODE>. If you want to see what are they, before you proceed, add the <EM>--show-layout</EM> option:
  +of the default <CODE>/usr/local/apache</CODE>. If you want to see what they are, before you proceed add the <EM>--show-layout</EM> option:
   
   <P>
   <PRE>  ./configure --prefix=/home/stas --show-layout
   </PRE>
   <P>
   You might want to put all the Apache files under <CODE>/home/stas/apache</CODE>
  -following the Apache's defaults convention. To accomplish that do:
  +following Apache's convention:
   
   <P>
   <PRE>  ./configure --prefix=/home/stas/apache
   </PRE>
   <P>
  -If you want to modify some or all of the automatically created names of
  -directories, when you omit their explicit parameters, just set them to the
  -desired values, e.g:
  +If you want to modify some or all of the names of the automatically created
  +directories:
   
   <P>
   <PRE>  ./configure --prefix=/home/stas/apache \
  @@ -2786,22 +2851,21 @@
   
   <P>
   Also remember that you can start the script only under a user and group you
  -belong to. Set the appropriate <CODE>User</CODE> and <CODE>Group</CODE>
  -directives in the <CODE>httpd.conf</CODE> to correct values.
  +belong to. You must set the <CODE>User</CODE> and <CODE>Group</CODE> directives in <EM>httpd.conf</EM> to appropriate values.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Actual_Local_mod_perl_Enabled_Ap">Actual Local mod_perl Enabled Apache Installation</A></H2></CENTER>
  +<CENTER><H2><A NAME="Local_mod_perl_Enabled_Apache_In">Local mod_perl Enabled Apache Installation</A></H2></CENTER>
   <P>
  -Now when we have learned how to install perl modules and Apache locally,
  -let's see how we use the acquired knowledge to install mod_perl enabled
  -Apache in our home directory. It's almost as simple as doing each one at
  -separate, but a single nuance you should know about and I'll mention it at
  -the end of this section.
  +Now when we have learned how to install local Apache and Perl modules
  +separately, let's see how to install mod_perl enabled Apache in our home
  +directory. It's almost as simple as doing each one separately, but there is
  +one wrinkle you need to know about which I'll mention at the end of this
  +section.
   
   <P>
  -So if you have unpacked Apache and mod_perl sources under the
  -<CODE>/home/stas/src</CODE> directory and they look like:
  +Let's say you have unpacked the Apache and mod_perl sources under
  +<EM>/home/stas/src</EM> and they look like this:
   
   <P>
   <PRE>  % ls /home/stas/src
  @@ -2809,9 +2873,10 @@
     /home/stas/src/mod_perl-x.xx
   </PRE>
   <P>
  -where <EM>x.xx</EM> are the version numbers as usual and you want the perl modules from the
  +where <EM>x.xx</EM> are the version numbers as usual. You want the Perl modules from the
   mod_perl package to be installed under
  -<CODE>/home/stas/lib/perl5</CODE> and Apache files under <CODE>/home/stas/apache</CODE>, the following commands will do that for you.
  +<EM>/home/stas/lib/perl5</EM> and the Apache files to go under
  +<EM>/home/stas/apache</EM>. The following commands will do that for you:
   
   <P>
   <PRE>  % perl Makefile.PL \
  @@ -2826,7 +2891,7 @@
     % make install
   </PRE>
   <P>
  -If you need something to be passed to <CODE>.configure</CODE> script as we have seen in the previous section use the <CODE>APACI_ARGS</CODE> parameter, e.g:
  +If you need some parameters to be passed to the <CODE>.configure</CODE> script, as we saw in the previous section use <CODE>APACI_ARGS</CODE>. For example:
   
   <P>
   <PRE>  APACI_ARGS=--sbindir=/home/stas/apache/sbin, \
  @@ -2837,17 +2902,17 @@
       --proxycachedir=/home/stas/apache/var/proxy
   </PRE>
   <P>
  -Note that the above multiline splitting will work only with <CODE>bash</CODE>
  -shell, <CODE>tcsh</CODE> users have to list all the parameters in a single line.
  +Note that the above multiline splitting will work only with <CODE>bash</CODE>,
  +<CODE>tcsh</CODE> users will have to list all the parameters on a single line.
   
   <P>
  -Basically the installation is complete. The only nuance is a <CODE>@INC</CODE>
  -variable, that wouldn't be correctly set if you rely on the
  -<CODE>PERL5LIB</CODE> environment variable, unless you set it explicitly in the startup file,
  -which is get required before any other module that resides in your local
  -repository is being loaded. But a much nicer approach is to use the <CODE>lib</CODE> pragma as we saw before, but in a little different way - we use it in the
  +Basically the installation is complete. The only remaining problem is the <CODE>@INC</CODE> variable. This won't be correctly set if you rely on the
  +<CODE>PERL5LIB</CODE> environment variable unless you set it explicitly in a startup file which
  +is <CODE>require</CODE>'d before loading any other module that resides in your local repository. A
  +much nicer approach is to use the
  +<CODE>lib</CODE> pragma as we saw before, but in a slightly different way - we use it in the
   startup file and it affects all the code that will be executed under
  -mod_perl handlers. e.g:
  +mod_perl handlers. For example:
   
   <P>
   <PRE>  PerlRequire /home/stas/apache/perl/startup.pl
  @@ -2859,36 +2924,35 @@
   <PRE>  use lib qw(/home/stas/lib/perl5/5.00503/
                /home/stas/lib/perl5/site_perl/5.005);
   </PRE>
  -<P>
  -Note that you can still use the hard-coded <CODE>@INC</CODE> modifications in the scripts themselves, but you should know that <CODE>@INC</CODE> would be reset to its original value after the scripts would be compiled
  -for the first time and all the hard-coded settings of <CODE>@INC</CODE> would be forgot.
  -
   <P>
  -That's because scripts modify <CODE>@INC</CODE> in <CODE>BEGIN</CODE> blocks and mod_perl executes the <CODE>BEGIN</CODE> blocks only when it does script compilation, that's why when you execute
  -the script for a second time, <CODE>@INC</CODE>
  -would be reset to its original value.
  +Note that you can still use the hard-coded <CODE>@INC</CODE> modifications in the scripts themselves, but be aware that scripts modify <CODE>@INC</CODE> in
  +<CODE>BEGIN</CODE> blocks and mod_perl executes the <CODE>BEGIN</CODE> blocks only when it does script compilation. As a result, <CODE>@INC</CODE> will be reset to its original value after the scripts are compiled and the
  +hard-coded settings will be forgotten. See the section '<A HREF="././porting.html#_INC_and_mod_perl">@INC and mod_perl</A>' for more information.
   
   <P>
  -The only place you can alter this ``original'' value is during the server
  -configuration stage either in the startup file or by setting:
  +The only place you can alter the ``original'' value is during the server
  +configuration stage either in the startup file or by putting
   
   <P>
   <PRE>  PerlSetEnv Perl5LIB /home/stas/lib/perl5/5.00503/:/home/stas/lib/perl5/site_perl/5.005
   </PRE>
   <P>
  -in the <CODE>httpd.conf</CODE>.
  +in <EM>httpd.conf</EM>.
   
   <P>
  -Now the rest of the mod_perl configuration and using is absolutely the same
  -as if you were installing mod_perl as a super user.
  +The rest of the mod_perl configuration and use is just the same as if you
  +were installing mod_perl as superuser.
   
   <P>
  -One more important thing to keep in mind is a system resources consuming.
  -mod_perl is memory hungry -- if you run a lot of mod_perl processes on a
  -public, multiuser (not dedicated) machine -- most likely the system
  -administrator of this machine will ask you to use less resources and even
  -to shut down your mod_perl server and to find another home for it. You have
  -a few solutions:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Resource_Usage">Resource Usage</A></H3></CENTER>
  +<P>
  +One more important thing to keep in mind is the consumption of system
  +resources. mod_perl is memory hungry. If you run a lot of mod_perl
  +processes on a public, multiuser machine, most likely the system
  +administrator of this machine will ask you to use less resources and may
  +even shut down your mod_perl server and ask you to find another home for
  +it. You have a few options:
   
   <UL>
   <P><LI>
  @@ -2897,17 +2961,16 @@
   
   <P><LI>
   <P>
  -Ask your ISP whether they can setup a dedicated machine for you in their
  -computer room, so you will be able to install as much memory as you need
  -and have the ISP to administer the system. But if you get a dedicated
  -machine chances are that you will want to have a root access if you are
  -able to manage the administering your self, keeping on the list of ISP's
  -responsibilities only the following items: keeping a constant electricity
  -supply, making sure that the network link is up, and protecting the machine
  -from possible physical break-ins (when someone breaks into a computer room
  -either to steal the information from your machine, or to damage it
  -physically). Another good idea is to let the ISP to install security
  -patches if you have a trust in them or just incapable of doing that.
  +Ask your ISP's system administrator whether they can setup a dedicated
  +machine for you, so that you will be able to install as much memory as you
  +need. If you get a dedicated machine the chances are that you will want to
  +have root access, so you may be able to manage the administration yourself.
  +Then you should consider keeping on the list of the system administrator's
  +responsibilities the following items: a reliable electricity supply and
  +network link. And of course making sure that the important security patches
  +get applied and the machine is configured to be secure. Finally having the
  +machine physically protected, so no one will turn off the power or break
  +it.
   
   <P><LI>
   <P>
  @@ -2921,15 +2984,13 @@
   <CENTER><H2><A NAME="Local_mod_perl_Enabled_Apache_In">Local mod_perl Enabled Apache Installation with CPAN.pm</A></H2></CENTER>
   <P>
   Again, CPAN makes installation and upgrades simpler. You have seen how to
  -install mod_perl enabled server using solely the <CODE>CPAN.pm</CODE>'s interactive shell. You have seen how to install perl modules and Apache
  -locally. Now all is left is to merge all these techniques into a single
  +install a mod_perl enabled server using <CODE>CPAN.pm</CODE>'s interactive shell. You have seen how to install Perl modules and Apache
  +locally. Now all you have to do is to merge these techniques into a single
   ``local mod_perl Enabled Apache Installation with CPAN.pm'' technique.
   
   <P>
  -Assuming that you have configured <CODE>CPAN.pm</CODE> to install perl modules locally, the installation is a very simple task.
  -Start the <CODE>CPAN.pm</CODE>
  -shell, set the arguments to be passed to <CODE>perl Makefile.PL</CODE> (modify the example setting to suit your needs), and tell &lt;CPAN.pm&gt;
  -to do the rest of the work for you:
  +Assuming that you have configured <CODE>CPAN.pm</CODE> to install Perl modules locally, the installation is very simple. Start the <CODE>CPAN.pm</CODE> shell, set the arguments to be passed to <CODE>perl Makefile.PL</CODE> (modify the example setting to suit your needs), and tell &lt;CPAN.pm&gt;
  +to do the rest for you:
   
   <P>
   <PRE>  % perl -MCPAN -eshell
  @@ -2937,15 +2998,28 @@
           PREFIX=/home/stas APACHE_PREFIX=/home/stas/apache'
     cpan&gt; install mod_perl
   </PRE>
  +<P>
  +When you use <CODE>CPAN.pm</CODE> for local installations, after the mod_perl installation is complete you
  +must make sure that the value of
  +<CODE>makepl_arg</CODE> is restored to its original value.
  +
   <P>
  -Since when you use <CODE>CPAN.pm</CODE> for local installations the value of
  -<CODE>makepl_arg</CODE> should be restored to its original value, when the mod_perl installation is
  -complete. The simplest solution is to quit the interactive shell and
  -reenter it if you need to install more modules. Doing that will reset the <CODE>makepl_arg</CODE> to its original value.
  +The simplest way to do this is to quit the interactive shell by typing
  +<EM>quit</EM> and reenter it. But if you insist here is how to make it work without
  +quitting the shell. You really want to skip this :)
   
  +<P>
  +If you want to continue working with <CODE>CPAN</CODE> *without* quitting the shell, you must:
  +
  +<OL>
  +<P><LI><STRONG><A NAME="item_remember_the_value_of_makepl_arg">remember the value of makepl_arg</A></STRONG>
  +<P><LI><STRONG><A NAME="item_change_it_to_suit_your_new_insta">change it to suit your new installation</A></STRONG>
  +<P><LI><STRONG><A NAME="item_build_and_install_mod_perl">build and install mod_perl</A></STRONG>
  +<P><LI><STRONG><A NAME="item_restore_it_after_completing_mod_">restore it after completing mod_perl installation</A></STRONG>
  +</OL>
   <P>
  -If you want to continue working with <CODE>CPAN</CODE> without quitting the shell, you've got to remember the value of <CODE>makepl_arg</CODE>, and restore it upon mod_perl installation completion. It's quite a
  -cumbersome task as of the this writing. I believe <CODE>CPAN.pm</CODE> will be improved to handle these issues more easily, when you read this.
  +this is quite a cumbersome task as of this writing, but I believe that
  +<CODE>CPAN.pm</CODE> will eventually be improved to handle this more easily.
   
   <P>
   So if you are still with me, start the shell as usual:
  @@ -2954,7 +3028,7 @@
   <PRE>  % perl -MCPAN -eshell
   </PRE>
   <P>
  -Read the value of the <CODE>makepl_arg</CODE>:
  +First, read the value of the <CODE>makepl_arg</CODE>:
   
   <P>
   <PRE>  cpan&gt; o conf makepl_arg 
  @@ -2963,29 +3037,31 @@
   <PRE>  PREFIX=/home/stas
   </PRE>
   <P>
  -It should be something like <CODE>PREFIX=/home/stas</CODE> if you configured
  +It will be something like <CODE>PREFIX=/home/stas</CODE> if you configured
   <CODE>CPAN.pm</CODE> to install modules locally. Save this value:
   
   <P>
   <PRE>  cpan&gt; o conf makepl_arg.save PREFIX=/home/stas
   </PRE>
   <P>
  -Now set a new value, to be used by mod_perl.
  +Second, set a new value, to be used by the mod_perl installation process.
  +(You can add parameters to this line, or remove them, according to your
  +needs.)
   
   <P>
   <PRE>  cpan&gt; o conf makepl_arg 'DO_HTTPD=1 USE_APACI=1 EVERYTHING=1 \
           PREFIX=/home/stas APACHE_PREFIX=/home/stas/apache'
   </PRE>
   <P>
  -Add or remove the parameters according to your needs. Now let
  -&lt;CPAN.pm&gt; to do the rest of the work for you:
  +Third, let &lt;CPAN.pm&gt; build and install mod_perl for you:
   
   <P>
   <PRE>  cpan&gt; install mod_perl
   </PRE>
   <P>
  -Now set <CODE>makepl_arg</CODE>'s original value back by printing the value of the saved variable and
  -assigning it to <CODE>makepl_arg</CODE>.
  +Fourth, reset the original value to <CODE>makepl_arg</CODE>. We do this by printing the value of the saved variable and assigning it
  +to
  +<CODE>makepl_arg</CODE>.
   
   <P>
   <PRE>  cpan&gt; o conf makepl_arg.save
  @@ -2994,10 +3070,12 @@
   <PRE>  PREFIX=/home/stas
   </PRE>
   <P>
  -<PRE>  cpan&gt; o conf makepl_arg.save PREFIX=/home/stas
  +<PRE>  cpan&gt; o conf makepl_arg PREFIX=/home/stas
   </PRE>
   <P>
  -Not so neat, but a working solution.
  +Not so neat, but a working solution. You could have written the value on a
  +piece of paper instead of saving it to makepl_arg.save, but you are more
  +likely to make a mistake that way.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -3015,14 +3093,14 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running</A></H1></CENTER>
  +<CENTER><H1><A NAME="How_can_I_tell_whether_mod_perl_">How can I tell whether mod_perl is running?</A></H1></CENTER>
   <P>
  -There are a few ways. In older versions of apache ( &lt; 1.3.6 ?) you could check that by running <CODE>httpd -v</CODE>, it no longer works. Now you should use <CODE>httpd -l</CODE>. Please notice that it is not enough to have it installed - you should of
  -course configure it for mod_perl and restart the server.
  +There are a few ways. In older versions of apache ( &lt; 1.3.6 ?) you could check that by running <CODE>httpd -v</CODE>, but it no longer works. Now you should use <CODE>httpd -l</CODE>. Please note that it is not enough to have it installed, you have to
  +configure it for mod_perl and restart the server too.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Testing_by_checking_the_error_lo">Testing by checking the error_log file</A></H2></CENTER>
  +<CENTER><H2><A NAME="Checking_the_error_log">Checking the error_log</A></H2></CENTER>
   <P>
   When starting the server, just check the <CODE>error_log</CODE> file for the following message:
   
  @@ -3043,8 +3121,8 @@
   You should see something like this:
   
   <P>
  -<PRE>  Embedded Perl version 5.00502 for Apache/1.3.1 (Unix) mod_perl/1.19 
  -  process 50880, running since Tue Oct 6 14:31:45 1998
  +<PRE>  Embedded Perl version 5.00503 for Apache/1.3.9 (Unix) mod_perl/1.21 
  +  process 50880, running since Mon Dec 6 14:31:45 1999
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -3066,20 +3144,26 @@
   
   <P>
   <PRE>  HTTP/1.1 200 OK
  -  Date: Tue, 01 Dec 1998 12:27:52 GMT
  -  Server: Apache/1.3.6 (Unix) mod_perl/1.19
  +  Date: Mon, 06 Dec 1999 12:27:52 GMT
  +  Server: Apache/1.3.9 (Unix) mod_perl/1.21
     Connection: close
     Content-Type: text/html
     
     Connection closed.
   </PRE>
  +<P>
  +The line
  +
  +<P>
  +<PRE>  Server: Apache/1.3.9 (Unix) mod_perl/1.21
  +</PRE>
   <P>
  -The line: <CODE>Server: Apache/1.3.6 (Unix) mod_perl/1.19</CODE> --confirms that you <STRONG>do</STRONG> have mod_perl installed and its version is <CODE>1.19</CODE>. Of course in your case it would be the version you have installed.
  +confirms that you have mod_perl installed and its version is <CODE>1.21</CODE>.
   
   <P>
   However, just because you have got mod_perl linked in there, that does not
   mean that you have configured your server to handle Perl scripts with
  -mod_perl. You will find the configuration assistance at
  +mod_perl. You will find configuration assistance at
   <A HREF="././config.html#">ModPerlConfiguration</A>
   
   
  @@ -3092,34 +3176,33 @@
   environment.
   
   <P>
  -I assume you have configured the server that scripts running under
  -<CODE>/perl/</CODE> location are handled by <CODE>Apache::Registry</CODE> handler. And you have the <CODE>PerlSendHeader</CODE> directive set to <CODE>On</CODE>.
  +I assume that you have configured the server so that scripts running under
  +location <EM>/perl/</EM> are handled by the <CODE>Apache::Registry</CODE>
  +handler and that you have the <CODE>PerlSendHeader</CODE> directive set to
  +<CODE>On</CODE>.
   
   <P>
  -Copy and paste the script below (no need for the first perl calling
  -(shebang) line!). Let's say you named it <CODE>test.pl</CODE>, saved it at the root of the CGI scripts and CGI root is mapped directly
  -to the
  -<CODE>/perl</CODE> location of your server.
  +Copy and paste the script below (no need for a shebang line!). Let's say
  +you name it <EM>test.pl</EM>, save it at the root of the CGI scripts and CGI root is mapped directly to
  +the <EM>/perl</EM> location of your server.
   
   <P>
  -<PRE>  print &quot;Content-type: text/plain\n\n&quot;;
  +<PRE>  print &quot;Content-type: text/plain\r\n\r\n&quot;;
     print &quot;Server's environment\n&quot;;
     foreach ( keys %ENV ) {
         print &quot;$_\t$ENV{$_}\n&quot;;
     }
   </PRE>
   <P>
  -Make it readable and executable by server:
  +Make it readable and executable by server (you may need to tune these
  +permissions on a public host):
   
   <P>
   <PRE>  % chmod a+rx test.pl
   </PRE>
  -<P>
  -(you will want to tune permissions on the public host).
  -
   <P>
  -Now fetch the URL <CODE>http://www.nowhere.com:8080/perl/test.pl</CODE> (replace 8080 with the port your mod_perl enabled server is listening to.
  -You should see something like this (the generated output was trimmed):
  +Now fetch the URL <CODE>http://www.nowhere.com:8080/perl/test.pl</CODE> (replace 8080 with the port your mod_perl enabled server is listening to).
  +You should see something like this (the output has been edited):
   
   <P>
   <PRE>  SERVER_SOFTWARE Apache/1.3.10-dev (Unix) mod_perl/1.21_01-dev
  @@ -3132,22 +3215,25 @@
   </PRE>
   <P>
   If you see the that the value of <CODE>GATEWAY_INTERFACE</CODE> is
  -<CODE>CGI-Perl/1.1</CODE> everything is OK. If you see:
  +<CODE>CGI-Perl/1.1</CODE> everything is OK. 
   
   <P>
  +If you there is an error you might have to add a shebang line
  +<CODE>#!/usr/bin/perl</CODE> as a first line of the CGI script and then try it again. If you see:
  +
  +<P>
   <PRE>  GATEWAY_INTERFACE       CGI/1.1
   </PRE>
   <P>
  -it means that you have configured this location to run under mod_cgi. But
  -actually the above script wouldn't run under mod_cgi, since you must use
  -the shebang line <CODE>#!/usr/bin/perl</CODE> as a first line of the CGI script
  +it means that you have configured this location to run under mod_cgi and
  +not mod_perl.
   
   <P>
  -Also note that there is a <CODE>MOD_PERL</CODE> environment variable if you run under mod_perl handler, and it's set to a
  +Also note that there is a <CODE>MOD_PERL</CODE> environment variable if you run under a mod_perl handler, it's set to the
   release number you use.
   
   <P>
  -Based on these differences you can write code like:
  +Based on these differences you can write code like this:
   
   <P>
   <PRE>  BEGIN {
  @@ -3155,7 +3241,7 @@
       $USE_MOD_PERL = exists $ENV{'GATEWAY_INTERFACE'}
                       and $ENV{'GATEWAY_INTERFACE'} =~ /CGI-Perl/
                       ? 1 : 0;
  -      # perl5.004 is a must under mod_perl
  +      # perl5.004 or better is a must under mod_perl
       require 5.004 if $USE_MOD_PERL;
     }
   </PRE>
  @@ -3171,21 +3257,20 @@
     }
   </PRE>
   <P>
  -You might wonder why in the world you would need to know in what handler
  -you are running under. For example you will want to use
  +You might wonder why in the world you would need to know what handler you
  +are running under. Well, for example you will want to use
   <CODE>Apache::exit()</CODE> and not <CODE>CORE::exit()</CODE> in your modules, but if you think that your script might be used in both
  -environments (mod_cgi vs. mod_perl), you will have to override the <CODE>exit()</CODE> subroutine and to make the runtime decision of what method you will use.
  -Not that if you run scripts under <CODE>Apache::Registry</CODE> handler, it takes care of overriding the <CODE>exit()</CODE> call for you, so it's not an issue if this is your case. For reasons and
  -implementations see:
  -<A HREF="././porting.html#Terminating_requests_and_process">Terminating requests and processes, exit()  function</A> 
  -and the whole <A HREF="././porting.html#">Writing Mod Perl scripts and Porting plain CGIs to it</A> page.
  +environments (mod_cgi and mod_perl) you will have to override the <CODE>exit()</CODE> subroutine and to make decision what method to use at the runtime.  
  +
  +<P>
  +Note that if you run scripts under the <CODE>Apache::Registry</CODE> handler, it takes care of overriding the <CODE>exit()</CODE> call for you, so it's not an issue. For reasons and implementations see: <A HREF="././porting.html#Terminating_requests_and_process">Terminating requests and processes, exit() function</A> and also <A HREF="././porting.html#">Writing Mod Perl scripts and Porting plain CGIs to it</A>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Testing_via_lwp_request">Testing via lwp-request</A></H2></CENTER>
   <P>
  -Yet another one. Why do I show all these approaches? While here they are
  -serving a very simple purpose, they can be helpful in other situations.
  +Yet another one. Why do I show all these approaches? While here they serve
  +a very simple purpose, they can be helpful in other situations.
   
   <P>
   Assuming you have the <CODE>libwww-perl</CODE> (<CODE>LWP</CODE>) package installed (you will need it installed in order to pass mod_perl's <CODE>make test</CODE> anyway):
  @@ -3194,75 +3279,79 @@
   <PRE>  % lwp-request -e -d <A HREF="http://www.nowhere.com">http://www.nowhere.com</A>
   </PRE>
   <P>
  -Will show you all the headers. (The <CODE>-d</CODE> option disables printing the response content.)
  +Will show you all the headers. The <CODE>-d</CODE> option disables printing the response content.
   
   <P>
   <PRE>  % lwp-request -e -d <A HREF="http://www.nowhere.com">http://www.nowhere.com</A> | egrep '^Server:'
   </PRE>
   <P>
  -To see the server's version only.
  +To see the server version only.
   
   <P>
  -Use <CODE>http://www.nowhere.com:port_number</CODE> if your server is listening to a non-default 80 port.
  +Use <CODE>http://www.nowhere.com:port_number</CODE> if your server is listening to a port other than port 80.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="General_Notes">General Notes</A></H1></CENTER>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Should_I_rebuild_mod_perl_if_I_h">Should I rebuild mod_perl if I have upgraded my perl?</A></H2></CENTER>
  +<CENTER><H2><A NAME="Should_I_Rebuild_mod_perl_if_I_h">Should I Rebuild mod_perl if I have Upgraded Perl?</A></H2></CENTER>
   <P>
  -Yes, you should. You have to rebuild mod_perl enabled server since it has a
  -hard coded <CODE>@INC</CODE> which points to the old perl and it is is probably linked to the an old <CODE>libperl</CODE> library. You can try to modify the <CODE>@INC</CODE> in the startup script (if you keep the old perl version around), but it is
  -better to build a fresh one to save you a mess.
  +Yes, you should. You have to rebuild the mod_perl enabled server since it
  +has a hard-coded <CODE>@INC</CODE> variable. This points to the old Perl and it is probably linked to an old <CODE>libperl</CODE> library. If for some reason you need to keep the old Perl version around
  +you can modify
  +<CODE>@INC</CODE> in the startup script, but it is better to build afresh to save you getting
  +into a mess.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Perl_installation_requirements">Perl installation requirements</A></H2></CENTER>
   <P>
  -Make sure you have perl installed -- the newer stable version you have the
  -better (minimum perl.5.004!). If you don't have it -- install it. Follow
  -the instructions in the distribution's <CODE>INSTALL</CODE>
  -file. During the configuration stage (while running <CODE>./Configure</CODE>), make sure you answer <CODE>YES</CODE> to the question:
  +Make sure you have Perl installed!. The latest stable version if possible.
  +Minimum perl.5.004! If you don't have it, install it. Follow the
  +instructions in the distribution's <CODE>INSTALL</CODE> file.
   
   <P>
  +During the configuration stage (while running <CODE>./Configure</CODE>), to be able to load dynamically Perl Modules extensions, make sure you
  +answer
  +<CODE>YES</CODE> to the question:
  +
  +<P>
   <PRE>  Do you wish to use dynamic loading? [y]
   </PRE>
   <P>
  -Answer <CODE>y</CODE> to be able to load dynamically Perl Modules extensions.
  -
  -<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="mod_auth_dbm_nuances">mod_auth_dbm nuances</A></H2></CENTER>
   <P>
  -If you are a user of <STRONG>mod_auth_dbm</STRONG> or <STRONG>mod_auth_db</STRONG>, you may need to edit Perl's <CODE>Config</CODE> module. When Perl is configured it attempts to find libraries for ndbm,
  +If you are a <CODE>mod_auth_dbm</CODE> or <CODE>mod_auth_db</CODE> user you may need to edit Perl's <CODE>Config</CODE> module. When Perl is configured it attempts to find libraries for ndbm,
   gdbm, db, etc., for the *DBM*_File modules. By default, these libraries are
  -linked with Perl and remembered by the <STRONG>Config</STRONG> module. When mod_perl is configured with apache, the <STRONG>ExtUtils::Embed</STRONG> module returns these libraries to be linked with httpd so Perl extensions
  +linked with Perl and remembered by the
  +<CODE>Config</CODE> module. When mod_perl is configured with apache, the
  +<CODE>ExtUtils::Embed</CODE> module returns these libraries to be linked with httpd so Perl extensions
   will work under mod_perl. However, the order in which these libraries are
  -stored in
  -<STRONG>Config.pm</STRONG>, may confuse <CODE>mod_auth_db*</CODE>. If <CODE>mod_auth_db*</CODE> does not work with mod_perl, take a look at this order with the following
  +stored in <STRONG>Config.pm</STRONG> may confuse
  +<CODE>mod_auth_db*</CODE>. If <CODE>mod_auth_db*</CODE> does not work with mod_perl, take a look at this order with the following
   command:
   
   <P>
   <PRE> % perl -V:libs
   </PRE>
   <P>
  -If <CODE>-lgdbm</CODE> or <CODE>-ldb</CODE> is before <CODE>-lndbm</CODE>, example:
  +Here's an example:
   
   <P>
   <PRE> libs='-lnet -lnsl_s -lgdbm -lndbm -ldb -ldld -lm -lc -lndir -lcrypt';
   </PRE>
   <P>
  -Edit <STRONG>Config.pm</STRONG> and move <CODE>-lgdbm</CODE> and <CODE>-ldb</CODE> to the end of the list. Here's how to find <STRONG>Config.pm</STRONG>:
  +If <CODE>-lgdbm</CODE> or <CODE>-ldb</CODE> is before <CODE>-lndbm</CODE> (as it is in the example) edit <EM>Config.pm</EM> and move <CODE>-lgdbm</CODE> and <CODE>-ldb</CODE> to the end of the list. Here's how to find <EM>Config.pm</EM>:
   
   <P>
   <PRE> % perl -MConfig -e 'print &quot;$Config{archlibexp}/Config.pm\n&quot;'
   </PRE>
   <P>
  -Another solution for building Apache/mod_perl+mod_auth_dbm under Solaris is
  -to remove the DBM and NDBM ``emulation'' from libgdbm.a. Seems Solaris
  -already provides its own DBM and NDBM, and there's no reason to build GDBM
  -with them (for us anyway).
  +Under Solaris, another solution for building Apache/mod_perl+mod_auth_dbm
  +is to remove the DBM and NDBM ``emulation'' from <EM>libgdbm.a</EM>. It seems that Solaris already provides its own DBM and NDBM, and in our
  +installation we found there's no reason to build GDBM with them.
   
   <P>
   In our Makefile for GDBM, we changed
  @@ -3277,61 +3366,62 @@
   <PRE>  OBJS = $(GDBM_OF)
   </PRE>
   <P>
  -Rebuild libgdbm, then Apache/mod_perl.  
  +Rebuild libgdbm before Apache/mod_perl.  
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H2><A NAME="Stripping_apache_to_make_it_almo">Stripping apache to make it almost perl-server</A></H2></CENTER>
  +<CENTER><H2><A NAME="Stripping_Apache_to_make_it_almo">Stripping Apache to make it almost a Perl-server</A></H2></CENTER>
   <P>
   Since most of the functionality that various apache mod_* modules provide
  -is being implemented in <A HREF="#item_Apache_">Apache::{*}</A> 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>.
  +is implemented in <A HREF="#item_Apache_">Apache::{*}</A> Perl modules, it was reported that one can build an Apache server with
  +mod_perl only. If you can reduce the requirements to whatever mod_perl can
  +handle, you can eliminate almost 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 <CODE>mod_actions</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Saving_the_config_status_Files_w">Saving the config.status Files with mod_perl, php, ssl and Other Components</A></H2></CENTER>
   <P>
  -Typically, when building the bloated apache that sits behind squid or
  +Typically, when building the bloated Apache that sits behind Squid or
   whatever, you need mod_perl, php, mod_ssl and the rest. As you install each
  -they typically overwrite each other's <CODE>config.status</CODE> files. An advise is to save them after each step, so you would be able to
  -reproduce and reuse them later.
  +they typically overwrite each other's <CODE>config.status</CODE>
  +files. Save them after each step, so you will be able to reuse them later.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="What_Compiler_Should_Be_Used_to_">What Compiler Should Be Used to Build mod_perl?</A></H2></CENTER>
   <P>
  -All Perl modules that use C extensions, must be compiled using the same
  -compiler the perl was built with.
  +All Perl modules that use C extensions must be compiled using the same
  +compiler that your copy of Perl was built with.
   
   <P>
  -When you run <CODE>perl Makefile.PL</CODE>, a <EM>Makefile</EM> get created. This
  +When you run <CODE>perl Makefile.PL</CODE>, a <EM>Makefile</EM> is created. This
   <EM>Makefile</EM> includes the same compilation options that were used to build Perl itself.
  -(These are stored in <EM>Config.pm</EM> module and can be displayed with <CODE>Perl -V</CODE> command). So all these options are re-applied when compiling Perl modules. 
  +They are stored in the <EM>Config.pm</EM> module and can be displayed with <CODE>Perl -V</CODE> command. All these options are re-applied when compiling Perl modules.
   
   <P>
   If you use a different compiler to build Perl extensions, chances are that
  -the options that a different compiler uses won't be the same, or even
  -worse, they might be interpreted in a completely different way. So the code
  -either won't compile, would dump core file when used or behave in the most
  +the options that a different compiler uses won't be the same, or they might
  +be interpreted in a completely different way. So the code either won't
  +compile, it will dump core when run or maybe it will behave in the most
   unexpected ways.
   
   <P>
  -Since mod_perl, uses Perl, Apache and third party modules, and they all
  -work together, it's a must thing to use the same compiler while building
  -each of the components.
  +Since mod_perl uses Perl, Apache and third party modules, and they all work
  +together, it's a must to use the same compiler while building each of the
  +components.
   
   <P>
  -But you shouldn't worry about when compliling Perl modules since Perl will
  -choose what's right automatically, unless you override things. If you do
  -this, you are on your own...
  +You shouldn't worry about this when compliling Perl modules since Perl will
  +choose what's right automatically. Unless you override things. If you do
  +that, you are on your own...
   
   <P>
  -If you compile a non-Perl component separately, you should worry to use the
  -same compiler and the same options, used to build Perl. Hint: Take a look
  -at the <EM>Config.pm</EM> module or the output if <CODE>perl -V</CODE>.
  +If you compile a non-Perl component separately, you should make sure to use
  +the same compiler and the same options used to build Perl. Hint: Take a
  +look at the <EM>Config.pm</EM> module or the output of <CODE>perl
  +-V</CODE>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -3341,21 +3431,21 @@
   <P>
   Gary Shea &lt;<A HREF="mailto:shea@xmission.com">shea@xmission.com</A>&gt;
   discovered a nasty BSDI bug (seen in versions 2.1 and 3.0) related to
  -dynamic loading and two workarounds: 
  +dynamic loading and found two workarounds:
   
   <P>
  -Turns out they use <CODE>argv[0]</CODE> to determine where to find the link tables at run-time, so if a program
  -either changes <CODE>argv[0]</CODE>, or does a <CODE>chdir()</CODE> (like apache!), it can easily confuse the
  -dynamic loader. The short-term solutions to the problem are pitifully
  -simple. Either of the following will work:
  +It turns out that they use <CODE>argv[0]</CODE> to determine where to find the link tables at run-time, so if a program
  +either changes <CODE>argv[0]</CODE>, or does a <CODE>chdir()</CODE> (like Apache!) it can easily confuse the
  +dynamic loader. The short-term solutions to the problem are simple. Either
  +of the following will work:
   
   <P>
   1) Call httpd with a full path, e.g. /opt/www/bin/httpd
   
   <P>
  -2) Put the httpd you wish to run in a directory in your PATH before any
  -other directory containing a version of httpd, then call it as 'httpd' --
  -don't use a relative path!
  +2) Put the httpd you wish to run in a directory in your PATH <EM>before</EM>
  +any other directory containing a version of httpd, then call it as 'httpd'.
  +Don't use a relative path!
   
   </UL>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -3391,7 +3481,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/09/2000
  +	     <BR>Last Modified at 03/04/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.19      +2 -2      modperl-site/guide/intro.html
  
  Index: intro.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/intro.html,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- intro.html	2000/02/09 21:11:44	1.18
  +++ intro.html	2000/03/04 20:31:46	1.19
  @@ -270,7 +270,7 @@
   <P>
   If you find incorrect details or mistakes in my grammar, or you want to
   contribute to this document please feel free to send me an email at <A
  -HREF="mailto:sbekman@iname.com">sbekman@iname.com</A> .
  +HREF="mailto:stas@stason.org">stas@stason.org</A> .
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -692,7 +692,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 01/02/2000
  +	     <BR>Last Modified at 03/04/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.2       +3964 -3787modperl-site/guide/mod_perl_guide.pdf.gz
  
  	<<Binary file>>
  
  
  1.13      +120 -1    modperl-site/guide/modules.html
  
  Index: modules.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/modules.html,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- modules.html	2000/02/09 21:11:45	1.12
  +++ modules.html	2000/03/04 20:31:47	1.13
  @@ -28,6 +28,9 @@
   
   	<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_Watchdog_RunAway_Hang">Apache::Watchdog::RunAway - Hanging Processes Monitor and Terminator</A>
  +	<LI><A HREF="#Apache_VMonitor_Visual_System">Apache::VMonitor - Visual System and Apache Server Monitor</A>
  +	<LI><A HREF="#Apache_GTopLimit_Limit_Apache">Apache::GTopLimit - Limit Apache httpd processes</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_RegistryNG_Apache_Re">Apache::RegistryNG - Apache::Registry New Generation</A>
  @@ -162,6 +165,122 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_Watchdog_RunAway_Hang">Apache::Watchdog::RunAway - Hanging Processes Monitor and Terminator</A></H1></CENTER>
  +<P>
  +This module monitors hanging Apache/mod_perl processes. You define the time
  +in seconds after which the process to be counted as <EM>hanging</EM> or
  +<EM>run away</EM>.
  +
  +<P>
  +When the process is considered as <EM>hanging</EM> it will be killed and the event logged into a log file.
  +
  +<P>
  +Generally you should use the <CODE>amprapmon</CODE> program that bundled with this module's distribution package, but you can
  +write your own code using the module as well. See the <EM>amprapmon</EM> manpage for more info about it.
  +
  +<P>
  +Note that it requires an <CODE>Apache::Scoreboard</CODE> module to work.
  +
  +<P>
  +Referer to the <CODE>Apache::Watchdog::RunAway</CODE> manpage for the configuration details.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_VMonitor_Visual_System">Apache::VMonitor - Visual System and Apache Server Monitor</A></H1></CENTER>
  +<P>
  +(META: Move it here)
  +
  +<P>
  +<A HREF="././debug.html#Apache_VMonitor_Visual_Syste">Apache::VMonitor -- Visual System and Apache Server Monitor</A>
  +
  +
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Apache_GTopLimit_Limit_Apache">Apache::GTopLimit - Limit Apache httpd processes</A></H1></CENTER>
  +<P>
  +This module allows you to kill off Apache httpd processes if they grow too
  +large or have too little of shared memory. You can choose to set up the
  +process size limiter to check the process size on every request:
  +
  +<P>
  +<PRE>    # in your startup.pl:
  +    use Apache::GTopLimit;
  +</PRE>
  +<P>
  +<PRE>    # Control the life based on memory size
  +    # in KB, so this is 10MB
  +    $Apache::GTopLimit::MAX_PROCESS_SIZE = 10000;
  +</PRE>
  +<P>
  +<PRE>    # Control the life based on Shared memory size
  +    # in KB, so this is 4MB
  +    $Apache::GTopLimit::MIN_PROCESS_SHARED_SIZE = 4000;
  +</PRE>
  +<P>
  +<PRE>    # watch what happens  
  +    $Apache::GTopLimit::DEBUG = 1;
  +</PRE>
  +<P>
  +<PRE>    # in your httpd.conf:   
  +    PerlFixupHandler Apache::GTopLimit
  +    # you can set this up as any Perl*Handler that handles
  +    # part of the request, even the LogHandler will do.
  +</PRE>
  +<P>
  +Or you can just check those requests that are likely to get big or
  +unshared. This way of checking is also easier for those who are mostly just
  +running Apache::Registry scripts:
  +
  +<P>
  +<PRE>    # in your CGI:
  +    use Apache::GTopLimit;  
  +      # Max Process Size in KB
  +    Apache::GTopLimit-&gt;set_max_size(10000);
  +</PRE>
  +<P>
  +and/or:
  +
  +<P>
  +<PRE>    use Apache::GTopLimit;
  +       # Min Shared process Size in KB
  +    Apache::GTopLimit-&gt;set_min_shared_size(4000);
  +</PRE>
  +<P>
  +Since accessing the process info might add a little overhead, you may want
  +to only check the process size every N times. To do so, put this in your <EM>startup.pl</EM> or your code:
  +
  +<P>
  +<PRE>    $Apache::GTopLimit::CHECK_EVERY_N_REQUESTS = 2;
  +</PRE>
  +<P>
  +This will only check the process size every other time the process size
  +checker is called.
  +
  +<P>
  +This module was written in response to questions on the mod_perl mailing
  +list on how to tell the httpd process to exit if:
  +
  +<UL>
  +<P><LI>
  +<P>
  +its memory size goes beyond a specified limit
  +
  +<P><LI>
  +<P>
  +its shared memory size goes below a specified limit
  +
  +</UL>
  +<P>
  +Note: This module will run on platforms supported by <STRONG>GTop.pm</STRONG> a Perl interface to libgtop (which in turn needs <STRONG>libgtop</STRONG> : See <A
  +HREF="http://home-of-linux.org/gnome/libgtop/">http://home-of-linux.org/gnome/libgtop/</A>
  +).
  +
  +<P>
  +Referer to the <CODE>Apache::GTopLimit</CODE> manpage for more information.
  +
  +<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>
   <P>
   This package contains modules for manipulating client request data via the
  @@ -507,7 +626,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/05/2000
  +	     <BR>Last Modified at 02/29/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.24      +505 -74   modperl-site/guide/performance.html
  
  Index: performance.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/performance.html,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- performance.html	2000/02/09 21:11:45	1.23
  +++ performance.html	2000/03/04 20:31:47	1.24
  @@ -30,6 +30,8 @@
   	<LI><A HREF="#Analysis_of_Software_and_Hardwar">Analysis of Software and Hardware Requirements</A>
   	<LI><A HREF="#Sharing_Memory">Sharing Memory</A>
   	<LI><A HREF="#How_Shared_Is_My_Memory_">How Shared Is My Memory?</A>
  +	<LI><A HREF="#Calculating_Real_Memory_Usage">Calculating Real Memory Usage</A>
  +	<LI><A HREF="#Is_my_Code_Shared_">Is my Code Shared?</A>
   	<LI><A HREF="#Preload_Perl_Modules_at_Server_S">Preload Perl Modules at Server Startup</A>
   	<UL>
   
  @@ -44,7 +46,7 @@
   	<LI><A HREF="#Caching_Components_with_HTML_Ma">Caching Components with HTML::Mason</A>
   	<LI><A HREF="#KeepAlive">KeepAlive</A>
   	<LI><A HREF="#Upload_Download_of_Big_Files">Upload/Download of Big Files</A>
  -	<LI><A HREF="#Forking_or_Executing_Subprocesse">Forking or Executing Subprocesses from mod_perl</A>
  +	<LI><A HREF="#Forking_and_Executing_Subprocess">Forking and Executing Subprocesses from mod_perl</A>
   	<LI><A HREF="#Memory_leakage">Memory leakage</A>
   	<UL>
   
  @@ -102,8 +104,18 @@
   	<LI><A HREF="#Using_1_Under_mod_perl_and_Be">Using $|=1 Under mod_perl and Better print() Techniques.</A>
   	<LI><A HREF="#More_Reducing_Memory_Usage_Tips">More Reducing Memory Usage Tips</A>
   	<LI><A HREF="#Measuring_the_Subroutines_Memory">Measuring the Subroutines Memory Usage</A>
  +	<LI><A HREF="#Memory_Swapping_is_Considered_Ba">Memory Swapping is Considered Bad</A>
   	<LI><A HREF="#Code_Profiling">Code Profiling</A>
  +	<LI><A HREF="#Reducing_the_Number_of_stat_Ca">Reducing the Number of stat() Calls</A>
   	<LI><A HREF="#Object_Methods_Calls_Versus_Func">Object Methods Calls Versus Function Calls</A>
  +	<UL>
  +
  +		<LI><A HREF="#The_Overhead_with_Light_Subrouti">The Overhead with Light Subroutines</A>
  +		<LI><A HREF="#The_Overhead_with_Heavy_Subrouti">The Overhead with Heavy Subroutines</A>
  +		<LI><A HREF="#Are_All_Methods_Slower_than_Func">Are All Methods Slower than Functions?</A>
  +	</UL>
  +
  +	<LI><A HREF="#Imported_Symbols_and_Memory_Usag">Imported Symbols and Memory Usage</A>
   	<LI><A HREF="#Sending_Plain_HTML_as_Compressed">Sending Plain HTML as Compressed Output</A>
   	<LI><A HREF="#Increasing_Shared_Memory_With_me">Increasing Shared Memory With mergemem</A>
   </UL>
  @@ -306,6 +318,199 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Calculating_Real_Memory_Usage">Calculating Real Memory Usage</A></H1></CENTER>
  +<P>
  +You have learned how to measure the size of the process' shared memory, but
  +we still want to know what is the real memory usage, which is obviously
  +cannot be calculated by summing up the memory size of each process, because
  +it doesn't take into account the shared memory.
  +
  +<P>
  +On the other hand we cannot just substruct the shared memory size from the
  +total size to get the real memory usage numbers, because in reality each
  +process does a different task, therefore the shared memory is not the same
  +for all processes.
  +
  +<P>
  +How do we measure the real memory size used by the server we run. It's
  +probably would be a tough goal to give the exact number, but I've found a
  +way to get a pretty close number which was verified in the following way. I
  +have calculated the real memory used, by the technique you will see in the
  +moment, and then have stopped the Apache server and saw that the memory
  +usage report indicated that the total used memory went down by almost the
  +same number I've calculated. Note that some OSes do smart caching so you
  +may not see the memory usage decrease, when it actually happens.
  +
  +<P>
  +This is a technique I've used:
  +
  +<OL>
  +<P><LI>
  +<P>
  +For each process sum up the difference between shared and system memory. To
  +calculate a difference for a single process use:
  +
  +<P>
  +<PRE>  use GTop;
  +  my $proc_mem = GTop-&gt;new-&gt;proc_mem($$);
  +  my $diff     = $proc_mem-&gt;size - $proc_mem-&gt;share;
  +  print &quot;Difference is $diff bytes\n&quot;;
  +</PRE>
  +<P><LI>
  +<P>
  +Now if we add the shared memory size of the process with maximum shared
  +memory, we will get all the memory that actually is being used by all httpd
  +processes, but the parent process.
  +
  +<P><LI>
  +<P>
  +Finally, add the size of the parent process.
  +
  +</OL>
  +<P>
  +Please note that this might be incorrect for your system, so you use this
  +number on your own risk.
  +
  +<P>
  +I've used this technique to display a real memory usage in the module
  +<A HREF="././debug.html#Apache_VMonitor_Visual_Syste">Apache::VMonitor</A>, so instead of trying to manually calculate this number use this module to
  +do the job.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Is_my_Code_Shared_">Is my Code Shared?</A></H1></CENTER>
  +<P>
  +How do you learn whether the code you write is shared between the process
  +or not. Well, not all of the code, but some variables. For example, if you
  +have some variables that use a lot of memory and you want them to be
  +read-only. As you know the variable becomes unshared when the process
  +modifies its value.
  +
  +<P>
  +So imagine that you have this 10Mb in-memory database that resides in a
  +single variable, you perform various operations on it and want to make sure
  +that the variable is still shared. For example if you do some matching
  +regex processing on this variable and want to use the <CODE>pos()</CODE>
  +function, will it make the variable unshared or not?
  +
  +<P>
  +The <CODE>Apache::Peek</CODE> module comes to rescue, let's write a module called <EM>MyShared.pm</EM> which we preload at the server startup, so all the variables of this module
  +are initially shared by all children.
  +
  +<P>
  +<PRE>  MyShared.pm
  +  ---------
  +  package MyShared;
  +  use Apache::Peek;
  +  
  +  my $readonly = &quot;Chris&quot;;
  +  
  +  sub match{      $readonly =~ /\w/g;                  }
  +  sub print_pos{  print &quot;pos: &quot;, pos($readonly), &quot;\n&quot;; }
  +  sub dump {      Dump($readonly);                     }
  +  1; 
  +</PRE>
  +<P>
  +This module declares the package, loads the <CODE>Apache::Peek</CODE> module and defines the <CODE>$readonly</CODE> variable which is supposed to be a <EM>big</EM>
  +variable, but we will use a small one to simplify this example. 
  +
  +<P>
  +The module also defines three subroutines: <CODE>match()</CODE> that does a
  +simple character matching, <CODE>print_pos()</CODE> that prints the current
  +position of the matching engine inside the string that was last matched and
  +finally the <CODE>dump()</CODE> subroutine that calls the <CODE>Apache::Peek</CODE> module's <CODE>Dump()</CODE> function to dump a raw Perl data-type of the <CODE>$readonly</CODE>
  +variable.
  +
  +<P>
  +Now we write the script that prints the PID of the process and calls the
  +tree functions. The goal is to check whether <CODE>pos()</CODE> makes the
  +variable dirty and therefore unshared.
  +
  +<P>
  +<PRE>  share_test.pl
  +  -------
  +  use MyShared;
  +  print &quot;Content-type: text/plain\r\n\r\n&quot;;
  +  print &quot;PID: $$\n&quot;;
  +  MyShared::match();
  +  MyShared::print_pos();
  +  MyShared::dump();
  +</PRE>
  +<P>
  +Before you restart the server in <EM>httpd.conf</EM> set:
  +
  +<P>
  +<PRE>  MaxClients 2
  +</PRE>
  +<P>
  +for easier tracking. You need at least two servers to compare the print
  +outs of the test program, Having more than two can make the comparison
  +process harder.
  +
  +<P>
  +Now open two browser windows and issue the request for this script for a
  +several times in both windows, so you get different processes PID reported
  +in the two windows and each process has been called a different number of
  +times. 
  +
  +<P>
  +In the first window you will see something like that:
  +
  +<P>
  +<PRE>  PID: 27040
  +  pos: 1
  +  SV = PVMG(0x853db20) at 0x8250e8c
  +    REFCNT = 3
  +    FLAGS = (PADBUSY,PADMY,SMG,POK,pPOK)
  +    IV = 0
  +    NV = 0
  +    PV = 0x8271af0 &quot;Chris&quot;\0
  +    CUR = 5
  +    LEN = 6
  +    MAGIC = 0x853dd80
  +      MG_VIRTUAL = &amp;vtbl_mglob
  +      MG_TYPE = 'g'
  +      MG_LEN = 1
  +</PRE>
  +<P>
  +And in the second window:
  +
  +<P>
  +<PRE>  PID: 27041
  +  pos: 2
  +  SV = PVMG(0x853db20) at 0x8250e8c
  +    REFCNT = 3
  +    FLAGS = (PADBUSY,PADMY,SMG,POK,pPOK)
  +    IV = 0
  +    NV = 0
  +    PV = 0x8271af0 &quot;Chris&quot;\0
  +    CUR = 5
  +    LEN = 6
  +    MAGIC = 0x853dd80
  +      MG_VIRTUAL = &amp;vtbl_mglob
  +      MG_TYPE = 'g'
  +      MG_LEN = 2
  +</PRE>
  +<P>
  +We see that all the addresses are the same (<CODE>0x8250e8c</CODE> and
  +<CODE>0x8271af0</CODE>), therefore the variable data structure is almost completely shared. The
  +only difference is in <CODE>SV.MAGIC.MG_LEN</CODE>
  +record, which is not shared.
  +
  +<P>
  +So given that the <CODE>$readonly</CODE> variable is a big one, its value is still shared between the processes,
  +while part of the variable data structure is non-shared but it's almost
  +insignificant because it takes a very little memory space.
  +
  +<P>
  +Now if you need to compare more than variable, doing it by hand can be
  +quite time consuming and error prune. Therefore it's better to correct the
  +testing script to dump the Perl data-types into files (e.g
  +<EM>/tmp/dump.$$</EM>, where <CODE>$$</CODE> is the PID of the process) and then using <CODE>diff(1)</CODE> utility to
  +see whether there is some difference.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Preload_Perl_Modules_at_Server_S">Preload Perl Modules at Server Startup</A></H1></CENTER>
   <P>
   Use the <CODE>PerlRequire</CODE> and <CODE>PerlModule</CODE> directives to load commonly used modules such as <CODE>CGI.pm</CODE>, <CODE>DBI</CODE> and etc., when the server is started. On most systems, server children will
  @@ -447,7 +652,7 @@
   
   
   <P>
  -After <CODE>CGI.pm</CODE> preloaded and compiled with CGI-&gt;compile(':all');
  +After <CODE>CGI.pm</CODE> preloaded and compiled with CGI-&gt;<CODE>compile(':all');</CODE>
   
   <P>
   <PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  @@ -463,9 +668,8 @@
     httpd    188104  0.0  1.0 4188 2940      - A    17:05:27  0:00 httpd
   </PRE>
   <P>
  -Observation: the child httpd has grown by 1172K - no change! So does
  -CGI-&gt;compile(':all') help us? We probably do not use all the methods
  -which CGI provides, so in real use it's faster.
  +Observation: the child httpd has grown by 1172K - no change! So does CGI-&gt;<CODE>compile(':all')</CODE> help us? We probably do not use all the
  +methods which CGI provides, so in real use it's faster.
   
   <P>
   You might want to compile only the tags you are going to use, then you will
  @@ -486,7 +690,7 @@
   
   
   <P>
  -After <CODE>CGI.pm</CODE> was preloaded but NOT compiled with CGI-&gt;compile():
  +After <CODE>CGI.pm</CODE> was preloaded but NOT compiled with CGI-&gt;<CODE>compile():</CODE>
   
   <P>
   <PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  @@ -510,7 +714,7 @@
   
   
   <P>
  -After <CODE>CGI.pm</CODE> was preloaded and compiled with CGI-&gt;compile(':all'):
  +After <CODE>CGI.pm</CODE> was preloaded and compiled with CGI-&gt;<CODE>compile(':all'):</CODE>
   
   <P>
   <PRE>  USER        PID %CPU %MEM   SZ  RSS    TTY STAT    STIME  TIME COMMAND
  @@ -901,7 +1105,7 @@
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Forking_or_Executing_Subprocesse">Forking or Executing Subprocesses from mod_perl</A></H1></CENTER>
  +<CENTER><H1><A NAME="Forking_and_Executing_Subprocess">Forking and Executing Subprocesses from mod_perl</A></H1></CENTER>
   <P>
   Generally you should not fork from your mod_perl scripts, since when you
   do, you are forking the entire Apache Web server, lock, stock and barrel.
  @@ -930,9 +1134,17 @@
   <PRE>  $params=FreezeThaw::freeze(
           [all data to pass to the other process]
           );
  -  system(&quot;program.pl $params&quot;);
  +  system(&quot;program.pl&quot;, $params);
   </PRE>
   <P>
  +Notice that you do a <CODE>system()</CODE> call with arguments separated by
  +commas, rather than passing them all as a single argument. When you use
  +commas, shell won't try to parse (tokenize) the parameters, therefore you
  +don't have to worry about escaping unsafe shell characters. If you want
  +shell to parse the variables make sure to run the escape function, for
  +example the one from the <CODE>String::ShellQuote</CODE> package.
  +
  +<P>
   and in <CODE>program.pl</CODE> :
   
   <P>
  @@ -1108,6 +1320,11 @@
   parent, so chances are that you will want it to leave untouched.
   
   <P>
  +Of course if your child needs any of the <CODE>STDIN</CODE>, <CODE>STDOUT</CODE> or
  +<CODE>STDERR</CODE> you should reopen them. But you must unties the parent process, thus you
  +should close them first.
  +
  +<P>
   So now the code would look like this:
   
   <P>
  @@ -1117,7 +1334,6 @@
     
     defined (my $kid = fork) or die &quot;Cannot fork: $!\n&quot;;
     if ($kid) {
  -    waitpid($kid,0);
       print &quot;Parent has finished\n&quot;;
     } else {
         close STDIN;
  @@ -1128,6 +1344,10 @@
     }
   </PRE>
   <P>
  +Note that <CODE>waitpid()</CODE> call has gone. The <CODE>$SIG{CHLD} = IGNORE;</CODE>
  +statement protects us from zombies, as explained above.
  +
  +<P>
   Another, more portable, but slightly more expensive solution is to use a
   double fork approach.
   
  @@ -1605,7 +1825,7 @@
   <P>
   after the both URIs have been requested from the same child process that
   happened to serve your request. To make the debugging easier see
  -<A HREF="././control.html#Running_server_in_a_single_mode">run the server in single mode</A>.
  +<A HREF="././control.html#Running_a_Server_in_Single_Proce">run the server in single mode</A>.
   
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  @@ -1913,10 +2133,10 @@
   
   <P>
   Let's try it. We will simulate 10 users concurrently requesting a very
  -light script at <CODE>www.nowhere.com:81/test/test.pl</CODE>. Each simulated user makes 10 requests.
  +light script at <CODE>www.example.com:81/test/test.pl</CODE>. Each simulated user makes 10 requests.
   
   <P>
  -<PRE>  % ./ab -n 100 -c 10 www.nowhere.com:81/test/test.pl
  +<PRE>  % ./ab -n 100 -c 10 www.example.com:81/test/test.pl
   </PRE>
   <P>
   The results are:
  @@ -1951,7 +2171,7 @@
   requests):
   
   <P>
  -<PRE>  % ./ab -n 1000 -c 10 www.nowhere.com:81/perl/access/access.cgi
  +<PRE>  % ./ab -n 1000 -c 10 www.example.com:81/perl/access/access.cgi
     Concurrency Level:      10
     Complete requests:      1000
     Failed requests:        0
  @@ -1962,7 +2182,7 @@
   let's raise the number of concurrent users to 50:
   
   <P>
  -<PRE>  % ./ab -n 1000 -c 50 www.nowhere.com:81/perl/access/access.cgi
  +<PRE>  % ./ab -n 1000 -c 50 www.example.com:81/perl/access/access.cgi
     Complete requests:      1000
     Failed requests:        0
     Requests per second:    133.01
  @@ -1999,7 +2219,7 @@
   Simulate 50 users each generating a total of 20 requests:
   
   <P>
  -<PRE>  % ./ab -n 1000 -c 50 www.nowhere.com:81/perl/access/access.cgi
  +<PRE>  % ./ab -n 1000 -c 50 www.example.com:81/perl/access/access.cgi
   </PRE>
   <P>
   The benchmark timed out with the above configuration.... I watched the
  @@ -2087,7 +2307,7 @@
   <P>
   Running a mod_perl script with lots of mysql queries (the script under test
   is mysqld limited)
  -(http://www.nowhere.com:81/perl/access/access.cgi?do_sub=query_form), with
  +(http://www.example.com:81/perl/access/access.cgi?do_sub=query_form), with
   the configuration:
   
   <P>
  @@ -2119,7 +2339,7 @@
   
   <P>
   Now we will benchmark the same script without using the mysql (code limited
  -by perl only): (http://www.nowhere.com:81/perl/access/access.cgi), it's the
  +by perl only): (http://www.example.com:81/perl/access/access.cgi), it's the
   same script but it just returns the HTML form, without making SQL queries.
   
   <P>
  @@ -2325,7 +2545,7 @@
   Sample output:
   
   <P>
  -<PRE>  URL(s):          <A HREF="http://www.nowhere.com:81/perl/access/access.cgi">http://www.nowhere.com:81/perl/access/access.cgi</A>
  +<PRE>  URL(s):          <A HREF="http://www.example.com:81/perl/access/access.cgi">http://www.example.com:81/perl/access/access.cgi</A>
     Total Requests:  100
     Parallel Agents: 10
     Succeeded:       100 (100.00%)
  @@ -2352,8 +2572,8 @@
     my $nof_requests_total = 100; 
     my $timeout = 10;
     my @urls = (
  -            '<A HREF="http://www.nowhere.com:81/perl/faq_manager/faq_manager.pl">http://www.nowhere.com:81/perl/faq_manager/faq_manager.pl</A>',
  -            '<A HREF="http://www.nowhere.com:81/perl/access/access.cgi">http://www.nowhere.com:81/perl/access/access.cgi</A>',
  +            '<A HREF="http://www.example.com:81/perl/faq_manager/faq_manager.pl">http://www.example.com:81/perl/faq_manager/faq_manager.pl</A>',
  +            '<A HREF="http://www.example.com:81/perl/access/access.cgi">http://www.example.com:81/perl/access/access.cgi</A>',
              );
     
     
  @@ -2535,7 +2755,7 @@
   derive a much better formula:
   
   <P>
  -<PRE>               Total_RAM + Shared_RAM_per_Child * MaxClients
  +<PRE>               Total_RAM + Shared__RAM_per_Child * MaxClients
     MaxClients = ---------------------------------------------
                           Max_Process_Size - 1
   </PRE>
  @@ -2598,24 +2818,28 @@
   <CODE>MaxRequestsPerChild</CODE> is 0, then the process will live forever.
   
   <P>
  -Setting <CODE>MaxRequestsPerChild</CODE> to a non-zero limit has two beneficial effects: it solves some memory
  -leakage problems and it helps to reduce the number of processes when the
  -server load reduces.
  -
  -<P>
  -The first reason is the most crucial for mod_perl, since sloppy programming
  -will cause a child process to consume more memory after each request. If
  -left unbounded, then after a certain number of requests the children will
  -use up all the available memory and leave the server to die from memory
  -starvation. Note that sometimes standard system libraries leak memory too,
  -especially on OSes with bad memory management (e.g. Solaris 2.5 on x86
  -arch). If this is your case you can set <CODE>MaxRequestsPerChild</CODE> to a small number. This will allow the system to reclaim the memory that a
  -greedy child processes consumed, when it exits after <CODE>MaxRequestsPerChild</CODE> requests. But beware -- if you set this number too low, you will lose some
  -of the speed bonus you get from mod_perl. Consider using <CODE>Apache::PerlRun</CODE>
  -if this is the case. Also consider setting <CODE>MaxSpareServers</CODE> to a number close to <CODE>MaxClients</CODE>. This will improve the response time but your parent process will be very
  -busy respawning new children!
  +Setting <CODE>MaxRequestsPerChild</CODE> to a non-zero limit solves some memory leakage problems caused by sloppy
  +programming practices, whereas a child process consumes more memory after
  +each request.
   
   <P>
  +If left unbounded, then after a certain number of requests the children
  +will use up all the available memory and leave the server to die from
  +memory starvation. Note that sometimes standard system libraries leak
  +memory too, especially on OSes with bad memory management (e.g. Solaris 2.5
  +on x86 arch).
  +
  +<P>
  +If this is your case you can set <CODE>MaxRequestsPerChild</CODE> to a small number. This will allow the system to reclaim the memory that a
  +greedy child processes consumed, when it exits after
  +<CODE>MaxRequestsPerChild</CODE> requests.
  +
  +<P>
  +But beware -- if you set this number too low, you will lose some of the
  +speed bonus you get from mod_perl. Consider using
  +<CODE>Apache::PerlRun</CODE> if this is the case.
  +
  +<P>
   Another approach is to use <CODE>Apache::SizeLimit</CODE>. See <A HREF="././performance.html#Limiting_the_Size_of_the_Process">Limiting the size of processes</A>.
   
   <P>
  @@ -2625,7 +2849,7 @@
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H2><A NAME="Choosing_MinSpareServers_MaxSpa">Choosing MinSpareServers, MaxSpareServers and StartServers</A></H2></CENTER>
   <P>
  -With mod_perl enabled, it might take as much as 30 seconds from the time
  +With mod_perl enabled, it might take as much as 20 seconds from the time
   you start the server until it is ready to serve incoming requests. This
   delay depends on the OS, the number of preloaded modules and the process
   load of the machine. It's best to set
  @@ -3480,6 +3704,39 @@
   </OL>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Memory_Swapping_is_Considered_Ba">Memory Swapping is Considered Bad</A></H1></CENTER>
  +<P>
  +(META: check that you don't have a duplication somewhere in the text,
  +probably the MaxClients tuning section)
  +
  +<P>
  +When tuning the performance of your box, you must configure the software
  +that you run in a way that no memory swapping will happen. Even during the
  +peak hours.
  +
  +<P>
  +Swap memory is slow since it resides on the hard disc, which is much slower
  +than the RAM. When your machine starts to swap, because it's unable to cope
  +with a number of the processes it has to run, your machine will become
  +slower and slower until it'll completely halt its operations. When the CPU
  +has to page in and out the memory pages, things slow down, causing the
  +processing demands to go up, which in turn slows down the system even more
  +as more memory is required and this is provided by kerner using the
  +reserved swap space.
  +
  +<P>
  +This is the path to the machine halt, unless the resource demand is
  +suddenly goes down and allows the processes to catch up with their tasks
  +and go back to the normal usage of memory.
  +
  +<P>
  +For the swapping monitoring techniques see the section '<A HREF="././debug.html#Apache_VMonitor_Visual_Syste">Apache::VMonitor -- Visual System and Apache Server Monitor</A>'.
  +
  +<P>
  +For the mod_perl specific swapping preventing guideliness see the section '<A HREF="././performance.html#Choosing_MaxClients">Choosing MaxClients</A>'.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Code_Profiling">Code Profiling</A></H1></CENTER>
   <P>
   The profiling process helps you to determine which subroutines or just
  @@ -3668,12 +3925,193 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Reducing_the_Number_of_stat_Ca">Reducing the Number of stat() Calls</A></H1></CENTER>
  +<P>
  +If you watch the server calls trace, while this processes a request, you
  +will notice a few <CODE>stat()</CODE> calls are made. For example when I
  +execute <A
  +HREF="http://localhost/perl-status">http://localhost/perl-status</A> and I
  +have my DocRoot set to
  +<EM>/home/httpd/docs</EM> I see:
  +
  +<P>
  +<PRE>  [snip]
  +  stat(&quot;/home/httpd/docs/perl-status&quot;, 0xbffff8cc) = -1 
  +                      ENOENT (No such file or directory)
  +  stat(&quot;/home/httpd/docs&quot;, {st_mode=S_IFDIR|0755, 
  +                                 st_size=1024, ...}) = 0
  +  [snip]
  +</PRE>
  +<P>
  +when running the server under <CODE>strace</CODE> or <CODE>truss</CODE> utility.
  +
  +<P>
  +If you have some dynamically generated code (not from the script) and your
  +virtual relative URI is like <EM>/news/perl/mod_perl/summary</EM>
  +(there is no such a directory on the web server, the sub sections are only
  +used for requesting a specific report), this will generate
  +<CODE>five(!)</CODE> <CODE>stat()</CODE> calls, before the <CODE>DocumentRoot</CODE> will be found. You will see something like this:
  +
  +<P>
  +<PRE>  stat(&quot;/home/httpd/docs/news/perl/mod_perl/summary&quot;, 0xbffff744) = -1 
  +                      ENOENT (No such file or directory)
  +  stat(&quot;/home/httpd/docs/news/perl/mod_perl&quot;, 0xbffff744) = -1 
  +                      ENOENT (No such file or directory)
  +  stat(&quot;/home/httpd/docs/news/perl&quot;, 0xbffff744) = -1 
  +                      ENOENT (No such file or directory)
  +  stat(&quot;/home/httpd/docs/news&quot;, 0xbffff744) = -1 
  +                      ENOENT (No such file or directory)
  +  stat(&quot;/home/httpd/docs&quot;, {st_mode=S_IFDIR|0755, 
  +                                 st_size=1024, ...}) = 0
  +</PRE>
  +<P>
  +You should blame the installed by default <CODE>TransHandler</CODE> for this inefficiency. Of course you could supply your own one, which will
  +be smart enough not to look for this virtual path and immediately return
  +<CODE>OK</CODE>. But in case that you have some virtual host that serves only dynamically
  +generated documents, you can override the default
  +<CODE>PerlTransHandler</CODE> with this one:
  +
  +<P>
  +<PRE>  &lt;VirtualHost 10.10.10.10:80&gt;
  +    ...
  +    PerlTransHandler  Apache::OK
  +    ...
  +  &lt;/VirtualHost&gt;
  +</PRE>
  +<P>
  +As you see it will affect only this specific virtual host.
  +
  +<P>
  +This has the effect of short circuiting the normal <CODE>TransHandler</CODE>
  +processing of trying to find a filesystem component that matches the given
  +URI -- no more 'stat's!
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Object_Methods_Calls_Versus_Func">Object Methods Calls Versus Function Calls</A></H1></CENTER>
  +<P>
  +Which subroutine calling form is more efficient: OOP methods or functions?
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="The_Overhead_with_Light_Subrouti">The Overhead with Light Subroutines</A></H2></CENTER>
  +<P>
  +Let's do a benchmarking. We will start doing it using empty methods, which
  +will allow us to measure the real difference in the overhead each kind of
  +call introduces. We will use this code:
  +
  +<P>
  +<PRE>  bench_call1.pl
  +  --------------
  +  package Foo;
  +  
  +  use strict;
  +  use Benchmark;
  +  
  +  sub bar { };
  +  
  +  timethese(50_000, {
  +                 method   =&gt; sub { Foo-&gt;bar()      },
  +                 function =&gt; sub { Foo::bar('Foo');},
  +                });
  +</PRE>
  +<P>
  +The two calls are equivalent, since both pass the class name as their first
  +name, <EM>function</EM> does this explicitly, while <EM>method</EM> does this transparently.
  +
  +<P>
  +The benchmarking result:
  +
  +<P>
  +<PRE>  Benchmark: timing 50000 iterations of function, method...
  +    function:  0 wallclock secs ( 0.80 usr +  0.05 sys =  0.85 CPU)
  +      method:  1 wallclock secs ( 1.51 usr +  0.08 sys =  1.59 CPU)
  +</PRE>
  +<P>
  +We are are interested in the 'total CPU times' and not the 'wallclock
  +seconds'. It's possible that the load on the system was different for the
  +two tests while benchmarking, so the wallclock times give us no useful
  +information.
  +
  +<P>
  +We see that the <EM>method</EM> calling type is almost twice slower, than
  +<EM>function</EM>. 0.85 CPU compared to 1.59 CPU real execution time. Why does this happen?
  +Because the difference between functions and methods is the time taken to
  +resolve the pointer from the object, to find the module it belongs to and
  +then the actual method. Functions form has one parameter less to pass, less
  +stack operations, less time to get to the guts of the subroutine.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="The_Overhead_with_Heavy_Subrouti">The Overhead with Heavy Subroutines</A></H2></CENTER>
  +<P>
  +But that doesn't mean that you shouldn't use methods. Generally your
  +functions do something, and the more they do the less will be the
  +difference, because the overhead time is a number of a final length.
  +Therefore the longer execution time of the function the smaller the
  +relative overhead of the method call. The next bechmark proves this point:
  +
  +<P>
  +<PRE>  bench_call2.pl
  +  --------------
  +  package Foo;
  +  
  +  use strict;
  +  use Benchmark;
  +  
  +  sub bar { 
  +    my $class = shift;
  +  
  +    my ($x,$y) = (100,100);
  +    $y = log ($x ** 10)  for (0..20);
  +  };
  +  
  +  timethese(50_000, {
  +                 method   =&gt; sub { Foo-&gt;bar()      },
  +                 function =&gt; sub { Foo::bar('Foo');},
  +                });
  +</PRE>
   <P>
  -Which approach is more efficient: OOP methods or function calls?
  -<CODE>CGI.pm</CODE>, for example, allows you to work in both modes.
  +We get a very close benchmarks!
   
   <P>
  +<PRE>  function: 33 wallclock secs (15.81 usr +  1.12 sys = 16.93 CPU)
  +    method: 32 wallclock secs (18.02 usr +  1.34 sys = 19.36 CPU)
  +</PRE>
  +<P>
  +Let's make the subroutine <EM>bar</EM> even slower:
  +
  +<P>
  +<PRE>  sub bar { 
  +    my $class = shift;
  +  
  +    my ($x,$y) = (100,100);
  +    $y = log ($x ** 10)  for (0..40);
  +  };
  +</PRE>
  +<P>
  +And the result is amazing, the <EM>method</EM> call convention was faster then <EM>function</EM>:
  +
  +<P>
  +<PRE>  function: 81 wallclock secs (25.63 usr +  1.84 sys = 27.47 CPU)
  +    method: 61 wallclock secs (19.69 usr +  1.49 sys = 21.18 CPU)
  +</PRE>
  +<P>
  +In case your functions do very little, like the functions that generate
  +HTML tags in <CODE>CGI.pm</CODE>, the overhead might become a significant one. If your goal is speed you
  +might consider to use the
  +<EM>function</EM> form, but if you write a big and complicated application, it's much better
  +to use the <EM>method</EM> form, as it will make your code easier to develop, maintain and debug.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Are_All_Methods_Slower_than_Func">Are All Methods Slower than Functions?</A></H2></CENTER>
  +<P>
  +Some modules' API is misleading, for example <CODE>CGI.pm</CODE> allows you to execute its subroutined as functions and methods. As you will
  +see in a moment its function form of the calls is slower than the method
  +form because it does some woodoo work when the function form call is used.
  +
  +<P>
   <PRE>  use CGI;
     my $q = new CGI;
     $q-&gt;param('x',5);
  @@ -3688,10 +4126,11 @@
     my $x = param('x');
   </PRE>
   <P>
  -As usual, let's benchmark and compare:
  +As usual, let's benchmark some very light calls and compare. Ideally we
  +would expect the <EM>methods</EM> to be slower than <EM>functions</EM> based on the previous benchmarks:
   
   <P>
  -<PRE>  meth_vs_func.pl
  +<PRE>  bench_call3.pl
     ---------------
     use Benchmark;
     
  @@ -3700,50 +4139,42 @@
     my $q = new CGI;
     my $x;
     timethese
  -    (20000, 
  -     {
  -      'Method'   =&gt; sub {$q-&gt;param('x',5); $x = $q-&gt;param('x'); },
  -      'Function' =&gt; sub {param('x',5); $x = param('x');},
  +    (20000, {
  +      method   =&gt; sub {$q-&gt;param('x',5); $x = $q-&gt;param('x'); },
  +      function =&gt; sub {    param('x',5); $x =     param('x'); },
        });
   </PRE>
   <P>
   The benchmark is written is such a way that all the initializations are
  -done at the beginning, so that we get as accurate a picture of the
  -performance as we can. Let's do it:
  +done at the beginning, so that we get as accurate performance figures as
  +possible. Let's do it:
   
   <P>
  -<PRE>  % ./meth_vs_func.pl
  +<PRE>  % ./bench_call3.pl
     
  -  Function: 29 wallclock secs (25.19 usr +  0.13 sys = 25.32 CPU)
  -    Method: 28 wallclock secs (22.94 usr +  0.10 sys = 23.04 CPU)
  +  function: 51 wallclock secs (28.16 usr +  2.58 sys = 30.74 CPU)
  +    method: 39 wallclock secs (21.88 usr +  1.74 sys = 23.62 CPU)
   </PRE>
   <P>
  -We are are interested in the 'total CPU times' and not the 'wallclock
  -seconds'. It's possible that the load on the system was different for the
  -two tests while benchmarking, so the wallclock times give us no useful
  -information.
  -
  -<P>
  -As we can see methods are about 6% slower than functions. This number is
  -true for all methods in <CODE>CGI.pm</CODE> and other OOP modules as well. Why? Because the difference between
  -functions and methods is the time taken to resolve the pointer from the
  -object, to find the Module it belongs to and then the actual method.
  +As we can see methods are faster than functions, which seems to be wrong.
  +The explanation lays in the way <CODE>CGI.pm</CODE> is implemented.
  +<CODE>CGI.pm</CODE> uses some <EM>fancy</EM> tricks to make the same routine act both as a <EM>method</EM> and a plain <EM>function</EM>. The overhead of checking whether the arguments list looks like a <EM>method</EM> invocation or not, will mask the slight difference in time for the way the
  +function was called.
   
   <P>
  -If you maintain the data object in a package's global variable like
  -<CODE>CGI.pm</CODE> does, you also save a little more time since you don't have to pass it to
  -the function. One parameter less to pass, less stack operations, less time
  -to get to the guts of the function.
  +If you are intrigued and want to investigate further by yourself the
  +subroutine you want to explore is called <EM>self_or_default</EM>. The first line of this function short-circuits if you are using the
  +object methods, but the whole function is called if you are using the
  +functional forms. Therefore, the functional form should be slightly slower
  +than the object form.
   
   <P>
  -But this little overhead is insignificant for most of us, relative to the
  -benefits it gives when we have a big project to take care of. And with big
  -projects it's much easier to use the object oriented approach.
  -
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Imported_Symbols_and_Memory_Usag">Imported Symbols and Memory Usage</A></H1></CENTER>
   <P>
  -In addition there is a real memory hit when you import all of the function
  -into your process' memory. This can significantly enlarge memory
  -requirements, particularly when there are many child processes.
  +There is a real memory hit when you import all of the function into your
  +process' memory. This can significantly enlarge memory requirements,
  +particularly when there are many child processes.
   
   <P>
   In addition to polluting the namespace, when a process imports symbols from
  @@ -3889,7 +4320,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/07/2000
  +	     <BR>Last Modified at 03/04/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.25      +9 -8      modperl-site/guide/porting.html
  
  Index: porting.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/porting.html,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- porting.html	2000/02/09 21:11:46	1.24
  +++ porting.html	2000/03/04 20:31:47	1.25
  @@ -622,7 +622,7 @@
   </PRE>
   <P>
   To make sure you don't miss these bugs always test your CGI in
  -<A HREF="././control.html#Running_server_in_a_single_mode">single process mode</A>.
  +<A HREF="././control.html#Running_a_Server_in_Single_Proce">single process mode</A>.
   
   <P>
   To solve this particular <STRONG>/o</STRONG> modifier problem refer to <A HREF="././perl.html#Compiled_Regular_Expressions">Compiled Regular Expressions</A>.
  @@ -774,7 +774,7 @@
   <P>
   To make sure that you have set <CODE>@INC</CODE> correctly, configure
   <A HREF="././debug.html#Apache_Status_Embedded_inter">/perl-status location</A>, fetch <A
  -HREF="http://www.nowhere.com/perl-status?inc">http://www.nowhere.com/perl-status?inc</A>
  +HREF="http://www.example.com/perl-status?inc">http://www.example.com/perl-status?inc</A>
   and look at the bottom of the page, where the contents of <CODE>@INC</CODE> will be shown.
   
   <P>
  @@ -1829,7 +1829,7 @@
   </PRE>
   <P>
   Both scripts call <CODE>use Foo;</CODE>. Only the first one called will know about <CODE>Foo</CODE>. When you call the second script it will not know about
  -<CODE>Foo</CODE> at all--it's like you've forgotten to write <CODE>use Foo;</CODE>. Run the server in <A HREF="././control.html#Running_server_in_a_single_mode">single server mode</A> to detect this kind of bug immediately.
  +<CODE>Foo</CODE> at all--it's like you've forgotten to write <CODE>use Foo;</CODE>. Run the server in <A HREF="././control.html#Running_a_Server_in_Single_Proce">single server mode</A> to detect this kind of bug immediately.
   
   <P>
   You will see the following in the error_log file:
  @@ -2098,7 +2098,7 @@
   </PRE>
   <P>
   But you're throwing performance out the window either way. It's best not to
  -fork at all if you can avoid it. See the ``<A HREF="././performance.html#Forking_or_Executing_Subprocesse">Forking or Executing subprocesses from mod_perl</A>'' section to learn about implications of forking.
  +fork at all if you can avoid it. See the ``<A HREF="././performance.html#Forking_and_Executing_Subprocess">Forking or Executing subprocesses from mod_perl</A>'' section to learn about implications of forking.
   
   <P>
   Also read about <A HREF="././modules.html#Apache_SubProcess">Apache::SubProcess</A> for overriden <CODE>system()</CODE> and <CODE>exec()</CODE> implementations
  @@ -2199,9 +2199,10 @@
   The above is the code that is used by the <CODE>Apache::SizeLimit</CODE> module which terminates processes that grow bigger than a value you choose.
   
   <P>
  -<CODE>Apache::GTopLimit</CODE> (based on libgtop) is a similar module. It does the same thing, plus you
  -can configure it to terminate processes when their shared memory shrinks
  -below some specified size.
  +<A HREF="././modules.html#Apache_GTopLimit_Limit_Apache">Apache::GTopLimit</A> (based on
  +<EM>libgtop</EM> and <CODE>GTop.pm</CODE>) is a similar module. It does the same thing, plus you can configure it to
  +terminate processes when their shared memory shrinks below some specified
  +size.
   
   <P>
   As mentioned before, it is unnecessary to postpone the execution of
  @@ -3186,7 +3187,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/05/2000
  +	     <BR>Last Modified at 03/04/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.23      +410 -34   modperl-site/guide/scenario.html
  
  Index: scenario.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/scenario.html,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- scenario.html	2000/02/09 21:11:46	1.22
  +++ scenario.html	2000/03/04 20:31:47	1.23
  @@ -62,8 +62,36 @@
   		<LI><A HREF="#Tricks_Traps_and_Gotchas">Tricks, Traps and Gotchas</A>
   	</UL>
   
  -	<LI><A HREF="#Building_and_Using_mod_proxy">Building and Using mod_proxy</A>
  +	<LI><A HREF="#mod_proxy">mod_proxy</A>
  +	<UL>
  +
  +		<LI><A HREF="#Concepts_and_Configuration_Direc">Concepts and Configuration Directives</A>
  +		<UL>
  +
  +			<LI><A HREF="#ProxyPass">ProxyPass</A>
  +			<LI><A HREF="#ProxyPassReverse">ProxyPassReverse</A>
  +		</UL>
  +
  +		<LI><A HREF="#Buffering_Feature">Buffering Feature</A>
  +		<UL>
  +
  +			<LI><A HREF="#Setting_the_Buffering_Limits_on_">Setting the Buffering Limits on Various OSes</A>
  +			<UL>
  +
  +				<LI><A HREF="#IOBUFSIZE_Source_Code_Definition">IOBUFSIZE Source Code Definition</A>
  +				<LI><A HREF="#ProxyReceiveBufferSize_Configura">ProxyReceiveBufferSize Configuration Directive</A>
  +				<LI><A HREF="#Hacking_the_Code">Hacking the Code</A>
  +			</UL>
  +
  +		</UL>
  +
  +		<LI><A HREF="#Caching">Caching</A>
  +		<LI><A HREF="#Building_process">Building process</A>
  +	</UL>
  +
  +	<LI><A HREF="#mod_proxy_add_forward_and_X_Forw">mod_proxy_add_forward and X-Forwarded-For header</A>
   	<LI><A HREF="#HTTP_Authentication_With_Two_Ser">HTTP Authentication With Two Servers Plus a Proxy</A>
  +	<LI><A HREF="#mod_rewrite_Examples">mod_rewrite Examples</A>
   </UL>
   <!-- INDEX END -->
   
  @@ -516,6 +544,20 @@
       --proxycachedir=/usr/local/var/httpd_docs/proxy
   </PRE>
   <P>
  +Notice that you actually don't have to enlist all these options, it's
  +enough to replace them all with <CODE>--target=httpd_docs</CODE>.
  +
  +<P>
  +<PRE>  % ./configure --prefix=/usr/local \
  +    --target=httpd_docs
  +</PRE>
  +<P>
  +This will use the default directory layout, but will replace <EM>apache</EM>
  +with <EM>httpd_docs</EM> everywhere. It'll even rename <EM>apachectl</EM> to be
  +<EM>httpd_docsctl</EM>. But we will continue with the manual directory tuning in the scenario
  +below.
  +
  +<P>
   If you need some other modules, such as mod_rewrite and mod_include (SSI),
   add them to the end of this list:
   
  @@ -611,6 +653,18 @@
   breaking the configuration process.
   
   <P>
  +Notice that just like in httpd_docs configuration you can use
  +<CODE>--target=httpd_perl</CODE> instead of specifying each directory separately. Note that this option has
  +to be the very last argument in
  +<CODE>APACI_ARGS</CODE>, otherwise 'make test' tries to run ``httpd_perl,'' which fails.
  +
  +<P>
  +This will use the default directory layout, but will replace <EM>apache</EM>
  +with <EM>httpd_docs</EM> everywhere. It'll even rename <EM>apachectl</EM> to be
  +<EM>httpd_docsctl</EM>. But we will continue with the manual directory tuning in the scenario
  +below.
  +
  +<P>
   As with httpd_docs you might need other modules such as
   <CODE>mod_rewrite</CODE>, so add them at the end of this list:
   
  @@ -711,7 +765,7 @@
   number from firewalls and users, by using either mod_proxy's <CODE>ProxyPass</CODE> directive or a proxy server like Squid.
   
   <P>
  -For more details see <A HREF="././config.html#Publishing_Port_Numbers_Differen">Publishing Port Numbers Different From 80 </A>, <A HREF="././scenario.html#Running_One_Webserver_and_Squid_">Running One Webserver and Squid in httpd Accelerator Mode</A>, <A HREF="././scenario.html#Running_Two_webservers_and_Squid">Running Two Webservers and Squid in httpd Accelerator Mode</A> and <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A>.
  +For more details see <A HREF="././config.html#Publishing_Port_Numbers_Differen">Publishing Port Numbers Different From 80 </A>, <A HREF="././scenario.html#Running_One_Webserver_and_Squid_">Running One Webserver and Squid in httpd Accelerator Mode</A>, <A HREF="././scenario.html#Running_Two_webservers_and_Squid">Running Two Webservers and Squid in httpd Accelerator Mode</A> and <A HREF="././scenario.html#mod_proxy">Using mod_proxy</A>.
   
   <P>
   Now we proceed to the mod_perl specific directives. It will be a good idea
  @@ -1115,7 +1169,7 @@
   I'd still want the thing to be logged. &lt;/META&gt;
   
   <P>
  -See <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A> for information about <CODE>X-Forwarded-For</CODE>.
  +See <A HREF="././scenario.html#mod_proxy">Using mod_proxy</A> for information about <CODE>X-Forwarded-For</CODE>.
   
   <P>
   To save you some keystrokes, here is the whole modified <CODE>squid.conf</CODE>:
  @@ -1175,7 +1229,7 @@
   <CENTER><H1><A NAME="Running_One_Webserver_and_Squid_">Running One Webserver and Squid in httpd Accelerator Mode</A></H1></CENTER>
   <P>
   When I was first told about Squid, I thought: ``Hey, now I can drop the
  -<CODE>httpd_docs</CODE> server and to have just Squid and <CODE>httpd_perl</CODE>
  +<CODE>httpd_docs</CODE> server and have just Squid and the <CODE>httpd_perl</CODE>
   servers``. Since all my static objects will be cached by squid, I do not
   need the light <CODE>httpd_docs</CODE> server.
   
  @@ -1390,7 +1444,7 @@
   <P>
   It's easy to get the logger to log the original client's IP address and not
   the one that comes from proxy server. Look for
  -<CODE>mod_proxy_add_forward</CODE> at <A HREF="././scenario.html#Building_and_Using_mod_proxy">Building and Using mod_proxy</A> for hints.
  +<CODE>mod_proxy_add_forward</CODE> at <A HREF="././scenario.html#mod_proxy">Building and Using mod_proxy</A> for hints.
   
   <P><LI><STRONG><A NAME="item_Eliminating">Eliminating :8080's</A></STRONG>
   <P>
  @@ -1496,58 +1550,288 @@
   
   <P>
   Note that if you are using the
  -<A HREF="././scenario.html#Building_and_Using_mod_proxy"><CODE>X-Forwarded-For</CODE></A> HTTP header, then this subsection is of limited relevance to you.
  +<A HREF="././scenario.html#mod_proxy"><CODE>X-Forwarded-For</CODE></A> HTTP header, then this subsection is of limited relevance to you.
   
   </UL>
   <P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="mod_proxy">mod_proxy</A></H1></CENTER>
  +<P>
  +mod_proxy implements a proxy/cache for Apache. It implements proxying
  +capability for FTP, CONNECT (for SSL), HTTP/0.9, and HTTP/1.0. The module
  +can be configured to connect to other proxy modules for these and other
  +protocols.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Concepts_and_Configuration_Direc">Concepts and Configuration Directives</A></H2></CENTER>
  +<P>
  +In the following explanation, we will use <EM>www.example.com</EM> as the main server users access when they want to get some kind of service
  +and <EM>backend.example.com</EM> as a machine that does the heavy work. The main and the back-end are
  +different servers, they may coexist on the same machine and may not.
  +
  +<P>
  +The mod_proxy module is built into the server that answers to requests to
  +the <EM>www.example.com</EM> hostname. It doesn't matter what functionality is built into the <EM>backend.example.com</EM> server.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="ProxyPass">ProxyPass</A></H3></CENTER>
  +<P>
  +You can use <CODE>ProxyPass</CODE> configuration directive for mapping remote hosts into the space of the
  +local server; the local server does not act as a proxy in the conventional
  +sense, but appears to be a mirror of the remote server.
  +
  +<P>
  +Let's explore what this rule does:
  +
  +<P>
  +<PRE>  ProxyPass   /modperl/ <A HREF="http://backend.example.com/modperl/">http://backend.example.com/modperl/</A>
  +</PRE>
  +<P>
  +When user initiates a request to <A
  +HREF="http://www.example.com/modperl/foo.pl">http://www.example.com/modperl/foo.pl</A>,
  +the request will be redirected to <A
  +HREF="http://backend.example.com/modperl/foo.pl">http://backend.example.com/modperl/foo.pl</A>,
  +and starting from this moment user will see <A
  +HREF="http://backend.example.com/">http://backend.example.com/</A> in her
  +location window, instead of <A
  +HREF="http://www.example.com/.">http://www.example.com/.</A>
  +
  +<P>
  +You have probably noticed many examples from the real life Internet
  +deployment. Free-email service providers and other similar heavy online
  +services display the login or the main page from their main server, and
  +then when you log-in you see something like
  +<EM>x11.example.com</EM>, then <EM>w59.example.com</EM>, etc. These are the back-end servers that do the actual work.
  +
  +<P>
  +Obviously this is not quite nice solution, but usually users don't really
  +care about what they see in the location window. So you can get away with
  +this approach. As I'll show in a minute there is a better solution which
  +removes this caveat and provides even more useful functionalities.
  +
  +<P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  -<CENTER><H1><A NAME="Building_and_Using_mod_proxy">Building and Using mod_proxy</A></H1></CENTER>
  +<CENTER><H3><A NAME="ProxyPassReverse">ProxyPassReverse</A></H3></CENTER>
   <P>
  -To build it into apache just add <STRONG>--enable-module=proxy</STRONG> during the Apache <STRONG>configure</STRONG> stage.
  +This directive lets Apache adjust the URL in the <CODE>Location</CODE> header on HTTP redirect responses. For instance this is essential when
  +Apache is used as a reverse proxy to avoid by-passing the reverse proxy
  +because of HTTP redirects on the back-end servers which stay behind the
  +reverse proxy. Generally used in conjunction with <CODE>ProxyPass</CODE>
  +directive to build a complete front-end proxy server.
   
   <P>
  -Now we will talk about Apache's mod_proxy and understand how it works.
  +<PRE>  ProxyPass          /modperl/  <A HREF="http://backend.example.com/modperl/">http://backend.example.com/modperl/</A>
  +  ProxyPassReverse   /modperl/  <A HREF="http://backend.example.com/modperl/">http://backend.example.com/modperl/</A>
  +</PRE>
  +<P>
  +When user initiates a request to <A
  +HREF="http://www.example.com/modperl/foo.pl">http://www.example.com/modperl/foo.pl</A>,
  +the request will be redirected to <A
  +HREF="http://backend.example.com/modperl/foo.pl">http://backend.example.com/modperl/foo.pl</A>
  +but on the way back
  +<CODE>ProxyPassReverse</CODE> will correct the location URL to become <A
  +HREF="http://www.example.com/modperl/foo.pl">http://www.example.com/modperl/foo.pl</A>
  +. This happens absolutely transparently to user. User will never know that
  +something has happened to his request behind the scenes.
   
   <P>
  -The server on port 80 answers http requests directly and proxies the
  -mod_perl enabled server in the following way:
  +Note that this <CODE>ProxyPassReverse</CODE> directive can also be used in conjunction with the proxy pass-through
  +feature:
   
   <P>
  -<PRE>  ProxyPass        /modperl/ <A HREF="http://localhost:81/modperl/">http://localhost:81/modperl/</A>
  -  ProxyPassReverse /modperl/ <A HREF="http://localhost:81/modperl/">http://localhost:81/modperl/</A>
  +<PRE>  RewriteRule ... [P]
   </PRE>
   <P>
  -<CODE>ProxyPassReverse</CODE> is the saving grace here, that makes Apache win over Squid. It rewrites the
  -redirect on its way back to the original URI.
  +from mod_rewrite because its doesn't depend on a corresponding
  +<CODE>ProxyPass</CODE> directive.
   
   <P>
  -The proxy has a receive buffer for output from the heavy server. You can
  -control the buffer size with <CODE>ProxyReceiveBufferSize</CODE> directive:
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Buffering_Feature">Buffering Feature</A></H2></CENTER>
  +<P>
  +In addition to the correcting the URI on its way back from the back-end
  +server feature, mod_proxy provides a buffering services, mod_perl and
  +similar heavy modules benefit from. The buffering feature allows mod_perl
  +to pass the generated data to mod_proxy and move on serving new requests,
  +instead of waiting for a possibly slow client to receive all the data.
  +
  +<P>
  +This figure depicts this feature:
   
   <P>
  +<PRE>                [socket]                   wire     `o'
  +  [mod_perl] =&gt; [      ] =&gt; [mod_proxy] =&gt; ____ =&gt;  /|\
  +                [buffer]                            / \
  +</PRE>
  +<P>
  +From looking at this figure it's easy to see that the bottleneck is the
  +socket buffer; it has to be able to absorb all the data that mod_perl has
  +generated in order to untie the mod_perl process immediately.
  +
  +<P>
  +<CODE>ProxyReceiveBufferSize</CODE> is the name of the parameter that specifies the size of the socket buffer.
  +Configuring:
  +
  +<P>
   <PRE>  ProxyReceiveBufferSize 16384
   </PRE>
   <P>
  +will create a buffer of 16k in size. If mod_perl generates output which
  +size is under 16k, the process will be immediately untied and allowed to
  +serve new requests, if the output is bigger than 16k, the following process
  +is taking place:
  +
  +<OL>
  +<P><LI>
  +<P>
  +The first 16k will enter the system buffer.
  +
  +<P><LI>
  +<P>
  +mod_proxy picks the first 8k and sends down the wire.
  +
  +<P><LI>
  +<P>
  +mod_perl writes the next 8k into the place of the 8k of data that was just
  +picked by mod_proxy.
  +
  +</OL>
  +<P>
  +Stages 2 and 3 get repeated until mod_perl has run out of data it has to
  +send. When this happens, it goes on its own business and the stage 2 is
  +repeated until all the data was picked from the system buffer and sent down
  +the wire.
  +
  +<P>
  +Of course you want to set the buffer size as bigger as possible, since you
  +want the heavy mod_perl processes to be utilized in the most effective way,
  +so you don't want them waste their time waiting for a client to receive the
  +data, especially if a client has a slow downstream connection.
  +
  +<P>
  +As the <CODE>ProxyReceiveBufferSize</CODE> name states, its buffering feature applies only to <EM>downstream data</EM> (coming from the origin server to the proxy) and not upstream data. There
  +is no buffering of data uploaded from the client browser to the proxy, thus
  +you cannot use this technique to prevent the heavy mod_perl server from
  +being tied up during a large POST such as a file upload. Falling back to
  +mod_cgi seems to be the best solution for these specific scripts whose
  +major function is getting a big upstream.
  +
  +<P>
  +&lt;META: check this ---&gt; Of course just like mod_perl, mod_proxy writes
  +the data it proxy-passes into its outgoing socket buffer, therefore the
  +mod_proxy process gets released as soon as the last chuck of data was
  +deposited into this buffer, even if the client didn't completed the
  +downloading. The OS worries to complete the transfer and release the TCP
  +socket used for this transfer.
  +
  +<P>
  +Therefore if you don't use mod_proxy and mod_perl send its data directly to
  +the client, and you have a big socket buffer, the mod_perl process will be
  +released as soon as the last chunk of data will enter the buffer. Just like
  +with mod_proxy, OS will worry to complete the data transfer.
  +
  +<P>
  +&lt;based on this comment&gt; yes, too (but receive and transmit buffer may
  +be of different size, depending on the OS)
  +
  +<P>
  +The problem I don't know is, does the call to close the socket wait, until
  +all data is actually send successfully or not. If it doesn't wait, you may
  +not be noticed of any failure, but because the proxing Apache can write as
  +fast to the socket transmission buffer as he can read, it should be
  +possible that the proxing Apache copies all the data from the receive to
  +the transmission buffer and after that releasing the receive buffer, so the
  +mod_perl Apache is free to do other things, while the proxing Apache still
  +wait until the client returns the success of data transmission. (The last,
  +is the part I am not sure on)
  +
  +<P>
  +&lt;/META&gt;
  +
  +<P>
  +Unfortunately you cannot set the socket buffer size as large as you want
  +because there is a limit of the available physical memory and OS has its
  +own upper limits on the possible buffer size.
  +
  +<P>
  +It doesn't mean that you cannot change the OS imposed limits, but to do
  +that you have to know the techniques for doing that. In the next section we
  +will present a few OSes and the ways to achieve the upper limit rise.
  +
  +<P>
  +To solve the physical memory limits you just have to add more memory.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Setting_the_Buffering_Limits_on_">Setting the Buffering Limits on Various OSes</A></H3></CENTER>
  +<P>
  +As we just saw there are a few kinds of parameters we might want to adjust
  +for our needs.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H4><A NAME="IOBUFSIZE_Source_Code_Definition">IOBUFSIZE Source Code Definition</A></H4></CENTER>
  +<P>
  +The first one is the parameter that use by
  +<EM>proxy_util.c:ap_proxy_send_fb()</EM> to loop over content being proxy passed in 8K chunks (as of this writing),
  +passing that on to the client. In other words it specifies the size of the
  +data that is sent downstream the wire.
  +
  +<P>
  +This parameter is defined by the <CODE>IOBUFSIZE</CODE>:
  +
  +<P>
  +<PRE>  #define IOBUFSIZE 8192
  +</PRE>
  +<P>
  +You have no control over this setting in the server configuration file,
  +therefore you might want to change it in the source files, before you
  +compile the server.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H4><A NAME="ProxyReceiveBufferSize_Configura">ProxyReceiveBufferSize Configuration Directive</A></H4></CENTER>
  +<P>
  +You can control the socket buffer size with <CODE>ProxyReceiveBufferSize</CODE>
  +directive:
  +
  +<P>
  +<PRE>  ProxyReceiveBufferSize 16384
  +</PRE>
  +<P>
   The above setting will set a buffer size to be of 16Kb. If it is not set
   explicitly or if it is set to 0 then the default buffer size is used. The
   number should be an integral multiple of 512.
   
   <P>
  -To release the mod_perl server from waiting for the data transfer after it
  -has done all the processing, <CODE>ProxyReceiveBufferSize</CODE> should if possible be set to a value greater than the biggest response
  -produced by any mod_perl script, but no bigger. But you have an improvement
  -even if the buffer isn't always big enough to absorb all the data, since
  -those heavy processes that generate less output will be released
  -immediately.
  +Note that if you set the value of <CODE>ProxyReceiveBufferSize</CODE> bigger than the OS limit, the default value will be used.
   
   <P>
   Both the default and the maximum possible value of
  -<CODE>ProxyReceiveBufferSize</CODE> depend on the Operating System. For example on Linux with kernel 2.2.5 the
  -maximum and default values are either 32k or 64k (hint: grep the kernel
  -sources for the <CODE>SK_RMEM_MAX</CODE>
  -variable). If you set the value bigger than the limit, the default value
  -will be used.
  +<CODE>ProxyReceiveBufferSize</CODE> depend on the Operating System.
  +
  +<UL>
  +<P><LI><STRONG><A NAME="item_Linux">Linux</A></STRONG>
  +<P>
  +For 2.2 kernels the max limit is in <EM>/proc/sys/net/core/rmem_max</EM> and the default value is in <EM>/proc/sys/net/core/rmem_default</EM>. If you want to increase <CODE>RCVBUF</CODE> size above 65535, the default max value, you have to raise first the
  +absolute limit in
  +<EM>/proc/sys/net/core/rmem_max</EM>. To do that at the run time, execute this command to raise it to 128k:
  +
  +<P>
  +<PRE>  % echo 131072 &gt; /proc/sys/net/core/rmem_max
  +</PRE>
  +<P>
  +You probably want to put this command into <EM>/etc/rc.d/rc.local</EM> so the change would take effect at the system reboot.
  +
  +<P>
  +On Linux OS with kernel 2.2.5 the maximum and default values are either 32k
  +or 64k. You can also change the default and maximum values during the
  +kernel compilation, for that you should alter the
  +<CODE>SK_RMEM_DEFAULT</CODE> and <CODE>SK_RMEM_MAX</CODE> definitions respectively.
   
  +<P><LI><STRONG><A NAME="item_FreeBSD">FreeBSD</A></STRONG>
   <P>
   Under FreeBSD it's possible to configure the kernel to have bigger socket
   buffers:
  @@ -1555,23 +1839,76 @@
   <P>
   <PRE> % sysctl -w kern.ipc.maxsockbuf=2621440
   </PRE>
  +<P><LI><STRONG><A NAME="item_Solaris">Solaris</A></STRONG>
  +<P>
  +Under Solaris this upper limit is specified by <EM>tcp_max_buf</EM>
  +parameter and equals to 256k as reported.
  +
  +<P><LI><STRONG><A NAME="item_Non">Non Listed OSes</A></STRONG>
   <P>
  +If you use OS that is not listed here and know the required for this
  +section details, please submit them to me.
  +
  +</UL>
  +<P>
   When you tell the kernel to use bigger sockets you can set bigger values
   for <EM>ProxyReceiveBufferSize</EM>. e.g. 1Mb (1048576).
   
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H4><A NAME="Hacking_the_Code">Hacking the Code</A></H4></CENTER>
   <P>
  -As the name states, its buffering feature applies only to <STRONG>downstream
  -data</STRONG> (coming from the origin server to the proxy) and not upstream data. There
  -is no buffering of data being uploaded from the client browser to the
  -proxy, thus you cannot use this technique to prevent the httpd_perl server
  -from being tied up during a large POST such as a file upload.
  +Some folks have patched the Apache source code to make the application
  +buffer configurable as well. After the patch there were two configuration
  +directives available:
   
  +<UL>
  +<P><LI>
  +<P>
  +ProxyReceiveBufferSize -- sets the socket buffer size
  +
  +<P><LI>
  +<P>
  +ProxyInternalBufferSize sets the application buffer size
  +
  +</UL>
  +<P>
  +To patch the source rename <CODE>ap_breate()</CODE> to
  +<CODE>ap_bcreate_size()</CODE> and add a size parameter, which defaults to <EM>IOBUFSIZE</EM> if 0 is passed. Then add
  +
  +<P>
  +<PRE>  #define ap_bcreate(p,flags) ap_bcreate(p,flags,0)
  +</PRE>
   <P>
  +and add a new <CODE>ap_bcreate()</CODE> which calls
  +<CODE>ap_bcreate_size()</CODE> for binary compatibility.
  +
  +<P>
  +Actually the <CODE>ProxyReceiveBufferSize</CODE> should be called
  +<CODE>ProxySocketBufferSize</CODE>. This would also remove some of the confusion about what it actually does.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Caching">Caching</A></H2></CENTER>
  +<P>
  +META: complete the conf details
  +
  +<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 the Apache
   documentation for more details on configuration of this capability.
   
   <P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Building_process">Building process</A></H2></CENTER>
  +<P>
  +To build mod_proxy into Apache just add <STRONG>--enable-module=proxy</STRONG>
  +during the Apache <STRONG>./configure</STRONG> stage.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="mod_proxy_add_forward_and_X_Forw">mod_proxy_add_forward and X-Forwarded-For header</A></H1></CENTER>
  +<P>
   Ask Bjoern Hansen has written the <CODE>mod_proxy_add_forward</CODE> module for Apache. It sets the <CODE>X-Forwarded-For</CODE> field when doing a
   <CODE>ProxyPass</CODE>, similar to what Squid can do. Its location is specified in the help
   section. Basically, this module adds an extra HTTP header to proxying
  @@ -1653,6 +1990,45 @@
   The same applies to mod_ssl, if plugged into a front-end server. It will
   properly encode/decode all the SSL requests.
   
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="mod_rewrite_Examples">mod_rewrite Examples</A></H1></CENTER>
  +<P>
  +In the mod_proxy + mod_perl servers scenario, <CODE>ProxyPass</CODE> was used to redirect all requests to the mod_perl server, by matching the
  +beginning of the relative URI (e.g. <EM>/perl</EM>). What should you do if you want everything, but files with extensions
  +like <EM>.gif</EM> or
  +<EM>.cgi</EM>, to be proxypassed to the mod_perl server. These files are to to be served
  +by the light Apache server which carries the mod_procy module.
  +
  +<P>
  +<PRE>  RewriteEngine On
  +  # handle GIF and JPG images, traditional CGI's directly
  +  RewriteRule \.(gif|jpg|png|css|txt|cgi)$ - [last]
  +  RewriteRule ^/cgi-bin - [last]
  +  # pass off everything but images to the heavy-weight server via proxy
  +  RewriteRule ^/(.*)$ <A HREF="http://localhost:4077/">http://localhost:4077/</A>$1 [proxy]
  +</PRE>
  +<P>
  +The following example rewrites everything to mod_perl server. It handles
  +locally all the requests to the files with extensions <EM>gif,
  +jpg, png, css, txt, cgi</EM> and relative URIs starting with <EM>/cgi-bin</EM>
  +(e.g. if you want some scripts to be executed under mod_cgi)
  +
  +<P>
  +That is, first, handle locally what you want to handle locally, then hand
  +off everything else to the back-end guy.
  +
  +<P>
  +These is the configuration of the logging facilities. 
  +
  +<P>
  +<PRE>  RewriteLogLevel 1
  +  RewriteLog &quot;| /usr/local/apache_proxy/bin/rotatelogs \
  +  /usr/local/apache-common/logs/r_log 86400&quot;
  +</PRE>
  +<P>
  +It says: log all the rewrites thru the pipe to <CODE>rotatelogs</CODE> utility which will rotate the logs every 2 hours (86400 secs).
  +
   <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>
  @@ -1686,7 +2062,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/09/2000
  +	     <BR>Last Modified at 03/04/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.21      +170 -118  modperl-site/guide/snippets.html
  
  Index: snippets.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/snippets.html,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- snippets.html	2000/02/09 21:11:46	1.20
  +++ snippets.html	2000/03/04 20:31:48	1.21
  @@ -49,6 +49,7 @@
   	<LI><A HREF="#A_Simple_Handler_To_Print_The_En">A Simple Handler To Print The Environment Variables</A>
   	<LI><A HREF="#mod_rewrite_Based_On_Query_Strin">mod_rewrite Based On Query String and URI Implemented in Perl</A>
   	<LI><A HREF="#Setting_PerlHandler_Based_on_MIM">Setting PerlHandler Based on MIME Type</A>
  +	<LI><A HREF="#Using_DESTROY_to_Finalize_Output">Using DESTROY to Finalize Output</A>
   	<LI><A HREF="#Mysql_Backup_and_Restore_Scripts">Mysql Backup and Restore Scripts</A>
   </UL>
   <!-- INDEX END -->
  @@ -907,6 +908,154 @@
   </PRE>
   <P>
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="Using_DESTROY_to_Finalize_Output">Using DESTROY to Finalize Output</A></H1></CENTER>
  +<P>
  +Well, as it's always with Perl -- TMTOWTDI (There Is More Than One Way To
  +Do It), one of the readers is using <CODE>DESTROY</CODE> to finalize output, as a cheap means of buffering.
  +
  +<P>
  +<PRE>  package buffer;
  +  use Apache;
  +  
  +  sub new {
  +     my $class = shift;
  +     my $self = bless {
  +         'r' =&gt; shift,
  +         'message' =&gt; &quot;&quot;
  +     }, $class;
  +     $self-&gt;{apr} = Apache::Request-&gt;new($self-&gt;{r},
  +                                         POST_MAX=&gt;(32*1024));
  +     $self-&gt;content_type('text/plain');
  +     $self-&gt;{r}-&gt;no_cache(1);
  +  }
  +  
  +  sub message {
  +        my $self = shift;
  +        $self-&gt;{message} .= join(&quot;\n&quot;, @_);
  +  }
  +  
  +  sub DESTROY {
  +        my $self = shift;
  +        $self-&gt;{apr}-&gt;send_http_header;
  +        $self-&gt;{apr}-&gt;print($self-&gt;{message});
  +  }
  +  1;
  +</PRE>
  +<P>
  +Now you can have perl scripts like:
  +
  +<P>
  +<PRE>  use buffer;
  +  my $b = new buffer(shift);
  +  
  +  $b-&gt;message(p(&quot;Hello World&quot;));
  +  # end
  +</PRE>
  +<P>
  +and save a bunch of duplicate code across otherwise inconvenient gaggles of
  +small scripts.
  +
  +<P>
  +But suppose you also want to redirect the client under some circumstances,
  +and send a 302 HTTP result. You might try to code:
  +
  +<P>
  +<PRE>  sub redir {
  +        my $self = shift;
  +        $self-&gt;{redirect} = shift;
  +        exit;
  +  }
  +</PRE>
  +<P>
  +and re-code <CODE>DESTROY</CODE> as:
  +
  +<P>
  +<PRE>  sub DESTROY {
  +        my $self = shift;
  +        if ($self-&gt;{redirect}) {
  +                $self-&gt;{apr}-&gt;status{REDIRECT};
  +                $self-&gt;{apr}-&gt;header_out(&quot;Location&quot;, $self-&gt;{redirect});
  +                $self-&gt;{apr}-&gt;send_http_header;
  +                $self-&gt;{apr}-&gt;print($self-&gt;{redirect});
  +        } else {
  +                $self-&gt;{apr}-&gt;send_http_header;
  +                $self-&gt;{apr}-&gt;print($self-&gt;{message});
  +        }
  +  }
  +</PRE>
  +<P>
  +But you'll find that, while the browser redirects itself, mod_perl logs the
  +result code as 200. It turns out that <CODE>status()</CODE> only touches
  +the Apache response, and the log message is determined by the Apache return
  +code.
  +
  +<P>
  +Aha! So we'll change the <CODE>exit()</CODE> in <CODE>redir()</CODE> to
  +<CODE>exit(REDIRECT).</CODE> This fixes the log code, but causes a bogus <EM>"[error] 302"</EM> line in the
  +<EM>error_log</EM>. That comes from <CODE>Apache::Registry</CODE>:
  +
  +<P>
  +<PRE>  my $errsv = &quot;&quot;;
  +  if($@) {
  +      $errsv = $@;
  +      $@ = ''; #XXX fix me, if we don't do this Apache::exit() breaks
  +      $@{$uri} = $errsv;
  +  }
  +  
  +  if($errsv) {
  +      $r-&gt;log_error($errsv);
  +      return SERVER_ERROR unless $Debug &amp;&amp; $Debug &amp; 2;
  +      return Apache::Debug::dump($r, SERVER_ERROR);
  +  }
  +</PRE>
  +<P>
  +So you see that any time the return code causes <CODE>$@</CODE> to return true, we'll get an error line. Not wanting this, what can we do?
  +
  +<P>
  +We can hope that a future version of mod_perl will allow us to set the HTTP
  +result code independent from the handler return code (perhaps a
  +<CODE>log_status()</CODE> method? or at least an <CODE>Apache::LOG_HANDLER_RESULT</CODE>
  +config variable?).
  +
  +<P>
  +In the meantime, there's
  +<A HREF="././modules.html#Apache_RedirectLogFix">Apache::RedirectLogFix</A>. Place:
  +
  +<P>
  +<PRE>  PerlLogHandler Apache::RedirectLogFix
  +</PRE>
  +<P>
  +in your <EM>httpd.conf</EM> and take a look at the source code. Note that it requires us to return 200.
  +
  +<P>
  +<PRE>  package Apache::RedirectLogFix;
  +  
  +  use Apache::Constants qw(OK DECLINED REDIRECT);
  +  
  +  sub handler {
  +     my $r = shift;
  +     return DECLINED unless $r-&gt;handler &amp;&amp; ($r-&gt;handler eq &quot;perl-script&quot;);
  +  
  +     if(my $loc = $r-&gt;header_out(&quot;Location&quot;)) {
  +         if($r-&gt;status == 200 and substr($loc, 0, 1) ne &quot;/&quot;) {
  +             $r-&gt;status(REDIRECT);
  +             return OK
  +         }
  +     }
  +     return DECLINED;
  +  }
  +  
  +  1;
  +</PRE>
  +<P>
  +Now, if we wanted to do the same sort of thing for an error-500 handler, we
  +could write another <CODE>PerlLogHandler</CODE> (call it
  +<CODE>ServerErrorLogFix</CODE>). But we'll leave that as an exercise to the reader, and hope that it
  +won't be needed in the next mod_perl release. After all, it's a little
  +awkward to need a <CODE>LogHandler</CODE> to clean up after ourselves....
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   <CENTER><H1><A NAME="Mysql_Backup_and_Restore_Scripts">Mysql Backup and Restore Scripts</A></H1></CENTER>
   <P>
   Well, this is something off-topic but since many of us use mysql or other
  @@ -930,47 +1079,16 @@
   
   
   
  -<P>
  -<PRE>  #!/usr/bin/perl -w
  -  
  -  # this script should be run from the crontab every night or in shorter
  -  # intervals. This scripts does a few things.
  -  # 1. dump all the tables into a separate dump files (these dump files 
  -  # are ready for DB restore)
  -  # 2. backups the last update log file and create a new log file
  -  
  -  
  -  use strict;
  -  my $data_dir = &quot;/var/lib/mysql&quot;;
  -  my $update_log = &quot;$data_dir/www.bar.com&quot;;
  -  my $dump_dir  = &quot;$data_dir/dump&quot;;
  -  my $gzip_exec = &quot;/bin/gzip&quot;;
  -  my @db_names = qw(bugs mysql bonsai);
  -  my $mysql_admin_exec = &quot;/usr/bin/mysqladmin &quot;;
  -  
  -      # convert unix time to date + time
  -  my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
  -  my $time  = sprintf(&quot;%0.2d:%0.2d:%0.2d&quot;,$hour,$min,$sec);
  -  my $date  = sprintf(&quot;%0.2d.%0.2d.%0.4d&quot;,++$mon,$mday,$year+1900);
  -  my $timestamp = &quot;$date.$time&quot;;
  -  
  -  # dump all the DBs we want to backup
  -  foreach my $db_name (@db_names) {
  -    my $dump_file = &quot;$dump_dir/$timestamp.$db_name.dump&quot;;
  -    my $dump_command = &quot;/usr/bin/mysqldump -c -e -l -q --flush-logs $db_name &gt; $dump_file&quot;;
  -    system $dump_command;
  -  }
  -  
  -  # move update log to backup for later restore if needed
  -  rename $update_log, &quot;$dump_dir/$timestamp.log&quot; if -e $update_log;
  -  
  -  # restart the update log to log to a new file!
  -  `/usr/bin/mysqladmin refresh`;
  -  
  -  # compress all the created files
  -  system &quot;$gzip_exec $dump_dir/$timestamp.*&quot;;
  -</PRE>
  -<P>
  +
  +	       <p><a href="code/mysql-3.22.29_backup.pl"><code>mysql-3.22.29_backup.pl</code></a> -- This is the original code 
  +
  +</p>
  +	      
  +	       <p><a href="code/mysql-3.22.30+_backup.pl"><code>mysql-3.22.30+_backup.pl</code></a> -- This is the code modified to work with
  +mysql-3.22.30+ 
  +
  +</p>
  +	      <P>
   You might need to change the executable paths according to your system. And
   list the names of the databases you want to backup, using the <CODE>db_names</CODE> array.
   
  @@ -994,82 +1112,16 @@
   
   
   
  -<P>
  -<PRE>  #!/usr/bin/perl -w
  -  
  -  # this scripts restores the DBs
  -  
  -  # Usage: mysql.restore.pl update.log.gz dump.db1.gz [... dump.dbn.gz]
  -  # all files dump* are compressed as we expect them to be created by 
  -  # mysql.backup utility
  -  
  -  # example: 
  -  # % mysql.restore.pl myhostname.log.gz 12.10.1998.16:37:12.*.dump.gz
  -  
  -  # .dump.gz extension.
  -  
  -  use strict;
  -  
  -  use FindBin qw($Bin);
  -  
  -  my $data_dir   = &quot;/var/lib/mysql&quot;;
  -  my $dump_dir   = &quot;$data_dir/dump&quot;;
  -  my $gzip_exec  = &quot;/bin/gzip&quot;;
  -  my $mysql_exec = &quot;/usr/bin/mysql -f &quot;;
  -  my $mysql_backup_exec = &quot;$Bin/mysql.backup.pl&quot;;
  -  my $mysql_admin_exec  = &quot;/usr/bin/mysqladmin &quot;;
  -  
  -  my $update_log_file = '';
  -  my @dump_files = ();
  -  
  -  # split input files into an update log and the dump files
  -  foreach (@ARGV) {
  -    push(@dump_files, $_),next unless /\.log\.gz/;
  -    $update_log_file = $_;
  -  }
  -  
  -  die &quot;Usage: mysql.restore.pl update.log.gz dump.db1.gz [... dump.dbn.gz]\n&quot; 
  -    unless defined @dump_files and @dump_files &gt; 0;
  -  
  -  # load the dump files
  -  foreach (@dump_files) {
  -  
  -      # check the file exists
  -    warn(&quot;Can't locate $_&quot;),next unless -e $_;
  -  
  -      # extract the db name from the dump file
  -    my $db_name = $1 if /\d\d\.\d\d.\d\d.\d\d:\d\d:\d\d\.(\w+)\.dump\.gz/;
  -  
  -    warn(&quot;Can't extract DB name from the file name,
  -          probably an error in the file format&quot;),
  -            next unless defined $db_name and $db_name;
  -  
  -      # we want to drop the table since restore will rebuild it!
  -      # force to drop the db without confirmation
  -    my $drop_command = &quot;$mysql_admin_exec -f drop $db_name&quot;;
  -    system $drop_command;
  -  
  -    $drop_command = &quot;$mysql_admin_exec create $db_name&quot;;
  -    system $drop_command;
  -  
  -      # build the command and execute it
  -    my $restore_command = &quot;$gzip_exec -cd $_ | $mysql_exec $db_name&quot;;
  -    system $restore_command;
  -  }
  -  
  -  # now load the update_log file (update the db with the changes since
  -  # the last dump
  -  warn(&quot;Can't locate $update_log_file&quot;),next unless  -e $update_log_file;
  -  
  -  my $restore_command = 
  -    &quot;$gzip_exec -cd $update_log_file |$mysql_exec&quot;;
  -  system $restore_command;
  -  
  -  # rerun the mysql.backup.pl since we have reloaded the dump files
  -  # and update log , and we must rebuild backups!
  -  system $mysql_backup_exec;
  -</PRE>
  -<P>
  +
  +	       <p><a href="code/mysql-3.22.29_restore.pl"><code>mysql-3.22.29_restore.pl</code></a> -- This is the original code
  +
  +</p>
  +	      
  +	       <p><a href="code/mysql-3.22.30+_restore.pl"><code>mysql-3.22.30+_restore.pl</code></a> -- This is the code modified to work with
  +mysql-3.22.30+
  +
  +</p>
  +	      <P>
   These are kinda dirty scripts, but they work... if you come up with a more
   clean scripts, please contribute... thanks
   
  @@ -1106,7 +1158,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/04/2000
  +	     <BR>Last Modified at 02/16/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.12      +273 -8    modperl-site/guide/strategy.html
  
  Index: strategy.html
  ===================================================================
  RCS file: /home/cvs/modperl-site/guide/strategy.html,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- strategy.html	2000/02/09 21:11:46	1.11
  +++ strategy.html	2000/03/04 20:31:48	1.12
  @@ -44,6 +44,21 @@
   		<LI><A HREF="#Apache_s_mod_proxy">Apache's mod_proxy</A>
   	</UL>
   
  +	<LI><A HREF="#When_One_Machine_is_not_Enough_f">When One Machine is not Enough for SQL DB and mod_perl</A>
  +	<UL>
  +
  +		<LI><A HREF="#Servers_Requirements">Servers' Requirements</A>
  +		<LI><A HREF="#The_Problem">The Problem</A>
  +		<LI><A HREF="#The_Solution">The Solution</A>
  +		<UL>
  +
  +			<LI><A HREF="#Pros">Pros</A>
  +			<LI><A HREF="#Cons">Cons</A>
  +		</UL>
  +
  +		<LI><A HREF="#Three_Machines_Model">Three Machines Model</A>
  +	</UL>
  +
   </UL>
   <!-- INDEX END -->
   
  @@ -177,7 +192,7 @@
   The DSO module (<CODE>mod_so</CODE>) adds size and complexity to your binaries.
   
   <P>
  -See <A HREF="././install.html#Build_mod_perl_as_DSO_inside_Apa">Build mod_perl as DSO inside Apache source tree via APACI</A>
  +See <A HREF="././install.html#Build_mod_perl_as_a_DSO_inside_t">Build mod_perl as DSO inside Apache source tree via APACI</A>
   
   
   
  @@ -496,11 +511,11 @@
   Using numbers is always more convincing :) Let's take a user connected to
   your site with 28.8 kbps (bps == bits/sec) modem. It means that the speed
   of the user's link is 28.8/8 = 3.6 kbytes/sec. I assume an average
  -generated HTML page to be of 10kb (kb == kilobytes) and an average script
  -that generates this output in 0.5 secs. How long will the server wait
  +generated HTML page to be of 40kb (kb == kilobytes) and an average script
  +that generates this output in 1 second. How long 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
  +reveals pretty scary numbers -- it will have to wait for another 12 secs
  +(40kb/3.6kb), when it could serve another 11 (12/1-1) dynamic requests in
   this time.
   
   <P>
  @@ -704,7 +719,7 @@
   </PRE>
   <P><LI>
   <P>
  -It does mod_perl output buffering like squid does. See the <A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A> notes for more details.
  +It does mod_perl output buffering like squid does. See the <A HREF="././scenario.html#mod_proxy">Using mod_proxy</A> notes for more details.
   
   <P><LI>
   <P>
  @@ -743,8 +758,258 @@
   (META: How fast is enough? :) Any figures here? 
   
   </UL>
  +<P>
  +For implementation see the ``<A HREF="././scenario.html#mod_proxy">Using mod_proxy</A>'' section in the implementation chapter.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H1><A NAME="When_One_Machine_is_not_Enough_f">When One Machine is not Enough for SQL DB and mod_perl</A></H1></CENTER>
  +<P>
  +You have begun your business as a small service providing web-site. After a
  +while your business becomes very popular and at some point you understand
  +that it has outgrown the capacity of your machine and you have moved
  +everything onto a stronger machine with more memory, a stronger CPU and a
  +faster hard disk.
  +
  +<P>
  +The situation comes back to normal but not for a long, as a demand for your
  +services keeps on growing and just a little time after you've upgraded your
  +machine, it cannot stand the load again. Should you buy an even stronger
  +and very expensive machine or start looking for another solution?
  +
  +<P>
  +A typical web service consists of two main software components, the
  +database server and the web server.
  +
  +<P>
  +A typical user-server interaction consists of accepting the query
  +parameters filled into an HTML form and submitted to the web server by a
  +user, converting these parameters into a database query, sending it to the
  +database server, accepting the results of the executed query, formatting
  +them into a nice HTML page, and sending it to a user's Internet browser or
  +another application that created the request.
  +
  +<P>
  +This figure depicts the above description:
  +
  +<P>
  +<PRE>             1                      2
  +  [      ] ====&gt; [               ] ====&gt; [                 ]
  +  [ User ]       [ Apache Server ]       [ Database Server ]
  +  [      ] &lt;==== [               ] &lt;==== [                 ]
  +             4                       3
  +</PRE>
  +<P>
  +This schema is known as a 3-tier architecture in the computing world.
  +
  +<P>
  +3-tier architecture means splitting up several processes of your computing
  +solution between different machines.
  +
  +<P>
  +1st you have the client, who will see the data on its screen and can give
  +instruction to modify or process the data. In our case, an Internet
  +browser.
  +
  +<P>
  +2nd you have the application server, which does the actual processing of
  +the data and sends it back to the client. In our case, a mod_perl enabled
  +apache server.
  +
  +<P>
  +3rd you have the database server, which stores and retrieves all the data
  +for the application server.
  +
  +<P>
  ++We are interested only in the 2nd and the 3rd tiers; we don't specify user
  +machine requirements, since mod_perl is all about server side programming.
  +The only thing the user should be able to do is to render the generated
  +HTML from the response, which any simple browser will do. Of course I'm not
  +talking about the case where you return some heavy Java applets, but that
  +movie is screened in another theater.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Servers_Requirements">Servers' Requirements</A></H2></CENTER>
  +<P>
  +Let's first understand what kind of software the web and database servers
  +are, what do they need to run fast and what implications they have on the
  +rest of the system software.
  +
  +<P>
  +The three important machine components are the hard disk, the amount of RAM
  +and the CPU type.
  +
  +<P>
  +In the average case the mod_perl server is mostly RAM hungry, while SQL
  +database server needs a very fast hard-disk the most. Of course if your
  +mod_perl process reads a lot from the disk (which is a quite infrequent
  +phenomenon) you will need a fast disk too. And if your database server has
  +to do a lot of sorting of the big tables and do lots of big table joins,
  +you will need a lot of RAM too.
  +
  +<P>
  +If we would specify average ``virtual'' requirements for each machine,
  +that's what we'd get:
  +
  +<P>
  +An <EM>"ideal"</EM> mod_perl machine:
  +
  +<P>
  +<PRE>  * HD:  low-end (no real IO, mostly logging)
  +  * RAM: the more the better
  +  * CPU: medium-high (according to needs)
  +</PRE>
  +<P>
  +An <EM>"ideal"</EM> database server machine:
  +
  +<P>
  +<PRE>  * HD:  high-end
  +  * RAM: big amount   (big joins, sorting of many records)
  +         small amount (otherwise)
  +  * CPU: medium-high (according to needs)
  +</PRE>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="The_Problem">The Problem</A></H2></CENTER>
  +<P>
  +With the database and the httpd on the same machine, you have conflicting
  +interests.
  +
  +<P>
  +During the peak load, Apache will spawn more processes and use RAM that the
  +database server might have been using, or that the kernel was using on its
  +behalf in the form of cache. You will starve your database of resources at
  +the time when it needs those resources the most.
  +
  +<P>
  +Disk I/O contention is the biggest time issue. Adding another disk wouldn't
  +cut I/O times because the database is the only one who does I/O - since
  +mod_perl processes has all the code loaded in memory. (I'm talking about
  +code that does pure perl and SQL processing) so it's clear that the DB is
  +I/O and CPU bounded (RAM only if there are big joins to make) and mod_perl
  +CPU and mostly RAM bounded.
  +
  +<P>
  +The problem exists, but it doesn't mean that you cannot run the application
  +and the web servers on the same machine. There is a very high degree of
  +parallelism in modern PC architecture. The I/O hardware is helpful here.
  +The machine can do many things while a SCSI subsystem is processing a
  +command, or the network hardware is writing a buffer over the wire.
  +
  +<P>
  +If a process is not runnable (that is, it is blocked waiting for I/O or
  +similar), it is not using significant CPU time. The only CPU time that will
  +be required to maintain a blocked process is the time it takes for the
  +operating system's scheduler to look at the process, decide that it is
  +still not runnable, and move on to the next process in the list. This is
  +hardly any time at all. If there are two processes and one of them is
  +blocked on I/O and the other is CPU bound, the blocked process is getting
  +0% CPU time, the runnable process is getting 99.9% CPU time, and the kernel
  +scheduler is using the remainder.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="The_Solution">The Solution</A></H2></CENTER>
  +<P>
  +Adding another machine, which allows a set-up where both the database and
  +the web servers run on its dedicated machine.
  +
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Pros">Pros</A></H3></CENTER>
  +<UL>
  +<P><LI><STRONG><A NAME="item_Hardware">Hardware Requirements</A></STRONG>
  +<P>
  +That allows you to scale two requirements independently.
  +
  +<P>
  +If your httpd processes are heavily weighted with respect to RAM
  +consumption, you can easily add another machine to accommodate more httpd
  +processes, without changing your database machine.
  +
  +<P>
  +If your database is CPU intensive, but your httpd doesn't need much CPU
  +time, you can get low end machines for the httpd and a high end machine
  +with a very fast CPU for the database server.
  +
  +<P><LI><STRONG><A NAME="item_Scalability">Scalability</A></STRONG>
  +<P>
  +Since your web server is not depending on the database server location any
  +more, you can add more web servers hitting the same database server, using
  +the existing infrastructure.
  +
  +<P><LI><STRONG><A NAME="item_Database">Database Security</A></STRONG>
  +<P>
  +Once you have multiple web server boxes the backend database becomes a
  +single point of failure so it's a good idea to shield it from direct
  +internet access, something you couldn't do when you had both servers on the
  +same machine.
  +
  +</UL>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H3><A NAME="Cons">Cons</A></H3></CENTER>
  +<UL>
  +<P><LI><STRONG><A NAME="item_Network">Network latency</A></STRONG>
  +<P>
  +When the request to the database server like mysql are made at the same
  +machine the database server is running on, it uses the UNIX sockets
  +compared to the TCP/IP socket when the client submits the query from
  +another machine. UNIX sockets are very fast since there is no network
  +delays, since all the communications happens within the same box. TCP/IP
  +sockets communication totally depends on the quality and the speed of the
  +network the two machines are connected with.
  +
  +<P>
  +Basically you can have almost the same client-server speed if you install a
  +very fast and dedicated network between the two machines. It might impose a
  +cost of additional NICs but it's probably insignificant compared to the
  +speed up you gain.
  +
  +<P>
  +But even the normal network that you have would probably fit as well,
  +because the networks delays are probably much smaller than the time it
  +takes to execute the query. In contrast to the previous paragraph, you
  +really want to test the added overhead, since the network can be quite slow
  +especially at the peak hours.
  +
  +<P>
  +How do you know what overhead is a significant one? All you have to measure
  +is the average time spent in the web server and the database server. If any
  +of the two numbers is at least 20 times bigger than the added overhead of
  +the network you are all set.
  +
  +<P>
  +To give you some numbers -- if your query takes about 20 milliseconds to
  +process and only 1 millisecond to deliver the results, it's good. If the
  +delivery takes about half of the time the processing takes you should start
  +thinking to switch to a faster and/or dedicated network.
  +
  +<P>
  +The implications of the slow network can be quite bad. If the network is
  +slow mod_perl processes remain open waiting for data from the database
  +server and eats even more RAM as new child processes pop up to handle new
  +requests. So the overall machine performance can be worse than it was
  +originally when you have had a single machine for both servers.
  +
  +</UL>
  +<P>
  +<P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
  +<CENTER><H2><A NAME="Three_Machines_Model">Three Machines Model</A></H2></CENTER>
  +<P>
  +Since we are talking about giving a dedicated machine for each server, you
  +might consider adding the third machine to do the proxy work, this will
  +make your setup even more flexible since it will enable you to proxy-pass
  +all request to more than one mod_perl running box, but many of them. It
  +will enable you doing a load balancing if and when you will need that.
  +
   <P>
  -For implementation see the ``<A HREF="././scenario.html#Building_and_Using_mod_proxy">Using mod_proxy</A>'' section in the implementation chapter.
  +Generally the proxy machine can be very light when they serve just a little
  +traffic and mainly proxy-pass to the mod_perl processes. Of course you can
  +put this machine to serve the static content and then the hardware
  +requirement will depend on the number of object you will have to serve and
  +the hit rate.
   
   <P><B><FONT SIZE=-1><A HREF="#toc">[TOC]</A></FONT></B><HR WIDTH="100%"></P>
   	     The <a href="http://www.modperl.com/">
  @@ -779,7 +1044,7 @@
       <B>
         <FONT SIZE=-1>
   	     Written by <A HREF="help.html#Contacting_me">Stas Bekman</A>.
  -	     <BR>Last Modified at 02/09/2000
  +	     <BR>Last Modified at 03/04/2000
         </FONT>
       </B>
     </TD>
  
  
  
  1.1                  modperl-site/guide/code/DB_File-Lock2.pm
  
  Index: DB_File-Lock2.pm
  ===================================================================
  package DB_File::Lock2;
  require 5.004;
  
  use strict;
  
  BEGIN {
      # RCS/CVS compliant:  must be all one line, for MakeMaker
    $DB_File::Lock2::VERSION = do { my @r = (q$Revision: 1.1 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
  
  }
  
  use DB_File ();
  use Fcntl qw(:flock O_RDWR O_CREAT);
  use Carp qw(croak carp verbose);
  use Symbol ();
  
  @DB_File::Lock2::ISA    = qw( DB_File );
  %DB_File::Lock2::lockfhs = ();
  
  use constant DEBUG => 0;
  
    # file creation permissions mode
  use constant PERM_MODE => 0660;
  
    # file locking modes
  %DB_File::Lock2::locks =
    (
     read  => LOCK_SH,
     write => LOCK_EX,
    );
  
  # SYNOPSIS:
  # tie my %mydb, 'DB_File::Lock2', $filepath, 
  #     ['read' || 'write', 'HASH' || 'BTREE']
  # while (my($k,$v) = each %mydb) {
  #   print "$k => $v\n";
  # }
  # untie %mydb;
  #########
  sub TIEHASH {
    my $class     = shift;
    my $file      = shift;
    my $lock_mode = lc shift || 'read';
    my $db_type   = shift || 'HASH';
  
    die "Dunno about lock mode: [$lock_mode].\n
         Valid modes are 'read' or 'write'.\n"
      unless $lock_mode eq 'read' or $lock_mode eq 'write';
  
    # Critical section starts here if in write mode!
  
      # create an external lock
    my $lockfh = Symbol::gensym();
    open $lockfh, ">$file.lock" or die "Cannot open $file.lock for writing: $!\n";
    unless (flock $lockfh, $DB_File::Lock2::locks{$lock_mode}) {
      croak "cannot flock: $lock_mode => $DB_File::Lock2::locks{$lock_mode}: $!\n";
    }
  
    my $self = $class->SUPER::TIEHASH
      ($file,
       O_RDWR|O_CREAT,
       PERM_MODE,
       ($db_type eq 'BTREE' ? $DB_File::DB_BTREE : $DB_File::DB_HASH )
      );
  
      # remove the package name in case re-blessing occurs
    (my $id = "$self") =~ s/^[^=]+=//;
  
      # cache the lock fh
    $DB_File::Lock2::lockfhs{$id} = $lockfh;
  
    return $self;
  
  } # end of sub new
  
  
  # DESTROY is automatically called when a tied variable
  # goes out of scope, on explicit untie() or when the program is
  # interrupted, e.g. with a die() call.
  # 
  # It unties the db by forwarding it to the parent class,
  # unlocks the file and removes it from the cache of locks.
  ###########
  sub DESTROY{
    my $self = shift;
  
    $self->SUPER::DESTROY(@_);
  
      # now it safe to unlock the file, (close() unlocks as well). Since
      # the object has gone we remove its lock filehandler entry
      # from the cache.
    (my $id = "$self") =~ s/^[^=]+=//; # see 'sub TIEHASH'
    close delete $DB_File::Lock2::lockfhs{$id};
  
      # Critical section ends here if in write mode!
  
    print "Destroying ".__PACKAGE__."\n" if DEBUG;
  
  }
  
  ####
  END {
    print "Calling the END from ".__PACKAGE__."\n" if DEBUG;
  
  }
  
  1;
  
  
  
  
  1.1                  modperl-site/guide/code/My-DB.pm
  
  Index: My-DB.pm
  ===================================================================
  package My::DB;
  
  use strict;
  use 5.004;
  
  use DBI;
  
  use vars qw(%c);
  use constant DEBUG => 0;
  
  %c =
    (
     db => {
  	  DB_NAME      => 'foo',
  	  SERVER       => 'localhost',
  	  USER         => 'put_username_here',
  	  USER_PASSWD  => 'put_passwd_here',
  	 },
  
    );
  
  use Carp qw(croak verbose);
  #local $SIG{__WARN__} = \&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 takes care of caching the connections
      # save into a dbh - Database handle object
    $self->{dbh} = DBI->connect("DBI:mysql:$c{db}{DB_NAME}::$c{db}{SERVER}",
  			       $c{db}{USER},
  			       $c{db}{USER_PASSWD},
  			       {
  				PrintError => 1, # warn() on errors
  				RaiseError => 0, # don't die on error
  				AutoCommit => 1, # commit executes immediately
  			       }
  			      )
      or DBI->disconnect("Cannot connect to database: $DBI::errstr\n");
  
      # we want to die on errors if in debug mode
    $self->{dbh}->{RaiseError} = 1 if DEBUG;
  
      # init the sth - Statement handle object
    $self->{sth} = '';
  
    bless ($self, $class);
  
    $self;
  
  } # end of sub new
  
  
  
  ######################################################################
                 ###################################
                 ###                             ###
                 ###       SQL Functions         ###
                 ###                             ###
                 ###################################
  ######################################################################
  
  # print debug messages
  sub d{
     # we want to print the trace in debug mode
    print "<DT><B>".join("<BR>", @_)."</B>\n" if DEBUG;
  
  } # end of sub d
  
  
  ######################################################################
  # return a count of matched rows, by conditions 
  #
  #  $count = sql_count_matched($table_name,\@conditions,\@restrictions);
  #
  # conditions must be an array so we can pass more than one column with
  # the same name.
  #
  #  @conditions =  ( column => ['comp_sign','value'],
  #                  foo    => ['>',15],
  #                  foo    => ['<',30],
  #                );
  #
  # The sub knows automatically to detect and quote strings
  #
  # Restrictions are the list of restrictions like ('order by email')
  #
  ##########################
  sub sql_count_matched{
    my $self    = shift;
    my $table   = shift || '';
    my $r_conds = shift || [];
    my $r_restr = shift || [];
  
      # we want to print the trace in debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
      # build the query
    my $do_sql = "SELECT COUNT(*) FROM $table ";
    my @where = ();
    for(my $i=0;$i<@{$r_conds};$i=$i+2) {
      push @where, join " ",
        $$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 .= "WHERE ". join " AND ", @where if @where;
  
      # restrictions (DONT put commas!)
    $do_sql .= " ". join " ", @{$r_restr} if @{$r_restr};
  
    d("SQL: $do_sql") if DEBUG;
  
      # do query
    $self->{sth} = $self->{dbh}->prepare($do_sql);
    $self->{sth}->execute();
    my ($count) = $self->{sth}->fetchrow_array;
  
    d("Result: $count") if DEBUG;
  
    $self->{sth}->finish;
  
    return $count;
  
  } # end of sub sql_count_matched
  
  
  ######################################################################
  # return a count of matched distinct rows, by conditions 
  #
  #  $count = sql_count_matched_distinct($table_name,\@conditions,\@restrictions);
  #
  # conditions must be an array so we can path more than one column with
  # the same name.
  #
  #  @conditions =  ( column => ['comp_sign','value'],
  #                  foo    => ['>',15],
  #                  foo    => ['<',30],
  #                );
  #
  # The sub knows automatically to detect and quote strings
  #
  # Restrictions are the list of restrictions like ('order by email')
  #
  # This a slow implementation - because it cannot use select(*), but
  # brings all the records in first and then counts them. In the next
  # version of mysql there will be an operator 'select (distinct *)'
  # which will make things much faster, so we will just change the
  # internals of this sub, without changing the code itself.
  #
  ##############################
  sub sql_count_matched_distinct{
    my $self    = shift;
    my $table   = shift || '';
    my $r_conds = shift || [];
    my $r_restr = shift || [];
  
      # we want to print the trace in debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
      # build the query
    my $do_sql = "SELECT DISTINCT * FROM $table ";
    my @where = ();
    for(my $i=0;$i<@{$r_conds};$i=$i+2) {
      push @where, join " ",
        $$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 .= "WHERE ". join " AND ", @where if @where;
  
      # restrictions (DONT put commas!)
    $do_sql .= " ". join " ", @{$r_restr} if @{$r_restr};
  
    d("SQL: $do_sql") if DEBUG;
  
      # do query
  #  $self->{sth} = $self->{dbh}->prepare($do_sql);
  #  $self->{sth}->execute();
  
    my $count = @{$self->{dbh}->selectall_arrayref($do_sql)};
  
  #  my ($count) = $self->{sth}->fetchrow_array;
  
    d("Result: $count") if DEBUG;
  
  #  $self->{sth}->finish;
  
    return $count;
  
  } # end of sub sql_count_matched_distinct
  
  
  
  ######################################################################
  # 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 => ['comp_sign','value'],
  #                  foo    => ['>',15],
  #                  foo    => ['<',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 the trace debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
      # build the query
    my $do_sql = "SELECT $column FROM $table ";
  
    my @where = ();
    for(my $i=0;$i<@{$r_conds};$i=$i+2) {
      push @where, join " ",
        $$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 .= " WHERE ". join " AND ", @where if @where;
  
      # restrictions (DONT put commas!)
    $do_sql .= " ". join " ", @{$r_restr} if @{$r_restr};
  
    d("SQL: $do_sql") if DEBUG;
  
      # do query
    return $self->{dbh}->selectrow_array($do_sql);
  
  } # end of sub sql_get_matched_value
  
  
  
  
  ######################################################################
  # 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 none 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 => ['comp_sign','value'],
  #                  foo    => ['>',15],
  #                  foo    => ['<',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 || [];
  
      # we want to print in the trace debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
      # build the query
    my $do_sql = "SELECT ";
    $do_sql .= join ",", @{$r_cols} if @{$r_cols};
    $do_sql .= " FROM $table ";
  
    my @where = ();
    for(my $i=0;$i<@{$r_conds};$i=$i+2) {
      push @where, join " ",
        $$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 .= " WHERE ". join " AND ", @where if @where;
  
      # restrictions (DONT put commas!)
    $do_sql .= " ". join " ", @{$r_restr} if @{$r_restr};
  
    d("SQL: $do_sql") if DEBUG;
  
      # do query
    @{$r_row} = $self->{dbh}->selectrow_array($do_sql);
  
  } # end of sub sql_get_matched_row
  
  
  
  ######################################################################
  # return a ref to hash of single matched row, by conditions
  # and restrictions. return undef if nothing matched.
  # (column1 => value1, column2 => value2) or empty () if non matched
  #
  # 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.
  #  @conditions =  ( column => ['comp_sign','value'],
  #                  foo    => ['>',15],
  #                  foo    => ['<',30],
  #                );
  # The sub knows automatically to detect and quote strings
  #
  # restrictions is a list of restrictions like ('order by email')
  #
  ##########################
  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 the trace debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
      # build the query
    my $do_sql = "SELECT ";
    $do_sql .= join ",", @{$r_cols} if @{$r_cols};
    $do_sql .= " FROM $table ";
  
    my @where = ();
    for(my $i=0;$i<@{$r_conds};$i=$i+2) {
      push @where, join " ",
        $$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 .= " WHERE ". join " AND ", @where if @where;
  
      # restrictions (DONT put commas!)
    $do_sql .= " ". join " ", @{$r_restr} if @{$r_restr};
  
    d("SQL: $do_sql") if DEBUG;
  
      # do query
    $self->{sth} = $self->{dbh}->prepare($do_sql);
    $self->{sth}->execute();
  
    return $self->{sth}->fetchrow_hashref;
  
  } # end of sub sql_get_hash_ref
  
  
  
  
  
  ######################################################################
  # 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 => ['comp_sign','value'],
  #                  foo    => ['>',15],
  #                  foo    => ['<',30],
  #                );
  # results in
  # WHERE foo > 15 AND foo < 30
  #
  #  to make an OR logic use (then ANDed )
  #  @conditions =  ( column => ['comp_sign',['value1','value2']],
  #                  foo    => ['=',[15,24] ],
  #                  bar    => ['=',[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 || [];
  
      # we want to print in the trace debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
      # build the query
    my $do_sql = "SELECT ";
    $do_sql .= join ",", @{$r_cols} if @{$r_cols};
    $do_sql .= " FROM $table ";
  
    my @where = ();
    for(my $i=0;$i<@{$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 {"($_)"} join " OR ",
  	map { join " ", 
  		$r_conds->[$i],
  		$r_conds->[$i+1][0],
  		sql_quote(sql_escape($_));
  	    } @{$r_conds->[$i+1][1]};
      } else {
          # single condition for the same field/comparator
        push @where, join " ",
  	$r_conds->[$i],
          $r_conds->[$i+1][0],
          sql_quote(sql_escape($r_conds->[$i+1][1]));
      }
    } # end of for(my $i=0;$i<@{$r_conds};$i=$i+2
  
      # Add the where clause if we have one
    $do_sql .= " WHERE ". join " AND ", @where if @where;
  
      # restrictions (DONT put commas!)
    $do_sql .= " ". join " ", @{$r_restr} if @{$r_restr};
  
    d("SQL: $do_sql") if DEBUG;
  
      # do query
    return $self->{dbh}->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 => value1 ,column2 => value2 , )
  #
  # $delayed: 1 => do delayed insert, 0 or none passed => 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 the trace debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
      # build the query
    my $do_sql = "INSERT $delayed INTO $table ";
    $do_sql   .= "(".join(",",keys %{$r_data}).")";
    $do_sql   .= " VALUES (";
    $do_sql   .= join ",", sql_quote(sql_escape( values %{$r_data} ) );
    $do_sql   .= ")";
  
    d("SQL: $do_sql") if DEBUG;
  
      # do query
    $self->{sth} = $self->{dbh}->prepare($do_sql);
    $self->{sth}->execute();
  
  } # end of sub sql_insert_row
  
  
  ######################################################################
  # update rows in a DB by condition
  #
  #  sql_update_rows($table_name,\%data,\@conditions,$delayed);
  #
  # data is hash of type (column1 => value1 ,column2 => value2 , )
  #
  # conditions must be an array so we can path more than one column with
  # the same name.
  #  @conditions =  ( column => ['comp_sign','value'],
  #                  foo    => ['>',15],
  #                  foo    => ['<',30],
  #                ); 
  #
  # $delayed: 1 => do delayed insert, 0 or none passed => 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' : '';
  
      # we want to print in the trace debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
      # build the query
    my $do_sql = "UPDATE $delayed $table SET ";
    $do_sql   .= join ",", 
      map { "$_=".join "",sql_quote(sql_escape($$r_data{$_})) } keys %{$r_data};
  
    my @where = ();
    for(my $i=0;$i<@{$r_conds};$i=$i+2) {
      push @where, join " ",
        $$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 .= " WHERE ". join " AND ", @where if @where;
  
  
    d("SQL: $do_sql") if DEBUG;
  
      # do query
    $self->{sth} = $self->{dbh}->prepare($do_sql);
  
    $self->{sth}->execute();
  
  #  my ($count) = $self->{sth}->fetchrow_array;
  #
  #  d("Result: $count") if DEBUG;
  
  } # 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 => ['comp_sign','value'],
  #                  foo    => ['>',15],
  #                  foo    => ['<',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 the trace debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
      # build the query
    my $do_sql = "DELETE FROM $table ";
  
    my @where = ();
    for(my $i=0;$i<@{$r_conds};$i=$i+2) {
      push @where, join " ",
        $$r_conds[$i],
        $$r_conds[$i+1][0],
        sql_quote(sql_escape($$r_conds[$i+1][1]));
    }
  
      # Must be very careful with deletes, imagine somehow @where is
      # not getting set, "DELETE FROM NAME" deletes the contents of the table
    warn("Attempt to delete a whole table $table from DB\n!!!"),return unless @where;
  
      # Add the where clause if we have one
    $do_sql .= " WHERE ". join " AND ", @where;
  
    d("SQL: $do_sql") if DEBUG;
  
      # do query
    $self->{sth} = $self->{dbh}->prepare($do_sql);
    $self->{sth}->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 the trace debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
    d("SQL: $do_sql") if DEBUG;
  
    $self->{dbh}->selectall_arrayref($do_sql);
  
  } # end of sub sql_execute_and_get_r_array
  
  
  ######################################################################
  # lock the passed tables in the requested mode (READ|WRITE) and set
  # internal flag to handle possible user abortions, so the tables will
  # be unlocked thru the END{} block
  #
  # sql_lock_tables('table1','lockmode',..,'tableN','lockmode'
  # lockmode = (READ | WRITE)
  #
  # _side_effect_ $self->{lock} = 'On';
  #
  ##########################
  sub sql_lock_tables{
    my $self   = shift;
    my %modes = @_;
  
    return unless %modes;
  
    my $do_sql = 'LOCK TABLES ';
    $do_sql .= join ",", map {"$_ $modes{$_}"} keys %modes;
  
      # we want to print the trace in debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
    d("SQL: $do_sql") if DEBUG;
  
    $self->{sth} = $self->{dbh}->prepare($do_sql);
    $self->{sth}->execute();
  
      # Enough to set only one lock, unlock will remove them all
    $self->{lock} = 'On';
  
  } # end of sub sql_lock_tables
  
  
  
  ######################################################################
  # unlock all tables, unset internal flag to handle possible user
  # abortions, so the tables will be unlocked thru the END{} block
  #
  # sql_unlock_tables()
  #
  # _side_effect_: delete $self->{lock}
  #
  ##########################
  sub sql_unlock_tables{
    my $self   = shift;
  
      # we want to print the trace in debug mode
    d( "[".(caller(2))[3]." - ".(caller(1))[3]." - ". (caller(0))[3]."]") if DEBUG;
  
    $self->{dbh}->do("UNLOCK TABLES");
  
      # Enough to set only one lock, unlock will remove them all
    delete $self->{lock};
  
  } # end of sub sql_unlock_tables
  
  #
  #
  # return current date formatted for a DATE field type
  # YYYYMMDD
  #
  # Note: since this function actually doesn't need an object it's being
  # called without parameter as well as procedural call
  ############
  sub sql_date{
    my $self     = shift;
  
    my ($mday,$mon,$year) = (localtime)[3..5];
    return sprintf "%0.4d%0.2d%0.2d",1900+$year,++$mon,$mday;
  
  } # end of sub sql_date
  
  #
  #
  # return current date formatted for a DATE field type
  # YYYYMMDDHHMMSS
  #
  # Note: since this function actually doesn't need an object it's being
  # called without parameter as well as procedural call
  ############
  sub sql_datetime{
    my $self     = shift;
  
    my ($sec,$min,$hour,$mday,$mon,$year) = localtime();
    return sprintf "%0.4d%0.2d%0.2d%0.2d%0.2d%0.2d",1900+$year,++$mon,$mday,$hour,$min,$sec;
  
  } # end of sub sql_datetime
  
  
  # Quote the list of parameters.  Parameters consisting entirely of
  # digits (i.e. integers) are unquoted.
  # print sql_quote("one",2,"three"); => 'one', 2, 'three'
  #############
  sub sql_quote{ map{ /^(\d+|NULL)$/ ? $_ : "\'$_\'" } @_ }
  
  # Escape the list of parameters (all unsafe chars like ",' are escaped)
  # We make a copy of @_ since we might try to change the passed values,
  # producing an error when modification of a read-only value is 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->sql_unlock_tables() if $self->{lock};
    $self->{sth}->finish       if $self->{sth};
    $self->{dbh}->disconnect   if $self->{dbh};
  
  } # end of sub DESTROY
  
  # Don't remove
  1;
  
  
  
  1.1                  modperl-site/guide/code/mysql-3.22.29_backup.pl
  
  Index: mysql-3.22.29_backup.pl
  ===================================================================
  #!/usr/bin/perl -w
  
  # this script should be run from the crontab every night or in shorter
  # intervals. This scripts does a few things.
  # 1. dump all the tables into a separate dump files (these dump files 
  # are ready for DB restore)
  # 2. backups the last update log file and create a new log file
  
  
  use strict;
  my $data_dir = "/var/lib/mysql";
  my $update_log = "$data_dir/www.bar.com";
  my $dump_dir  = "$data_dir/dump";
  my $gzip_exec = "/bin/gzip";
  my @db_names = qw(bugs mysql bonsai);
  my $mysql_admin_exec = "/usr/bin/mysqladmin ";
  
      # convert unix time to date + time
  my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
  my $time  = sprintf("%0.2d:%0.2d:%0.2d",$hour,$min,$sec);
  my $date  = sprintf("%0.2d.%0.2d.%0.4d",++$mon,$mday,$year+1900);
  my $timestamp = "$date.$time";
  
  # dump all the DBs we want to backup
  foreach my $db_name (@db_names) {
    my $dump_file = "$dump_dir/$timestamp.$db_name.dump";
    my $dump_command = "/usr/bin/mysqldump -c -e -l -q --flush-logs $db_name > $dump_file";
    system $dump_command;
  }
  
  # move update log to backup for later restore if needed
  rename $update_log, "$dump_dir/$timestamp.log" if -e $update_log;
  
  # restart the update log to log to a new file!
  `/usr/bin/mysqladmin refresh`;
  
  # compress all the created files
  system "$gzip_exec $dump_dir/$timestamp.*";
  
  
  
  
  1.1                  modperl-site/guide/code/mysql-3.22.29_restore.pl
  
  Index: mysql-3.22.29_restore.pl
  ===================================================================
  #!/usr/bin/perl -w
  
  # this scripts restores the DBs
  
  # Usage: mysql.restore.pl update.log.gz dump.db1.gz [... dump.dbn.gz]
  # all files dump* are compressed as we expect them to be created by 
  # mysql.backup utility
  
  # example: 
  # % mysql.restore.pl myhostname.log.gz 12.10.1998.16:37:12.*.dump.gz
  
  # .dump.gz extension.
  
  use strict;
  
  use FindBin qw($Bin);
  
  my $data_dir   = "/var/lib/mysql";
  my $dump_dir   = "$data_dir/dump";
  my $gzip_exec  = "/bin/gzip";
  my $mysql_exec = "/usr/bin/mysql -f ";
  my $mysql_backup_exec = "$Bin/mysql.backup.pl";
  my $mysql_admin_exec  = "/usr/bin/mysqladmin ";
  
  my $update_log_file = '';
  my @dump_files = ();
  
  # split input files into an update log and the dump files
  foreach (@ARGV) {
    push(@dump_files, $_),next unless /\.log\.gz/;
    $update_log_file = $_;
  }
  
  die "Usage: mysql.restore.pl update.log.gz dump.db1.gz [... dump.dbn.gz]\n" 
    unless defined @dump_files and @dump_files > 0;
  
  # load the dump files
  foreach (@dump_files) {
  
      # check the file exists
    warn("Can't locate $_"),next unless -e $_;
  
      # extract the db name from the dump file
    my $db_name = $1 if /\d\d\.\d\d.\d\d.\d\d:\d\d:\d\d\.(\w+)\.dump\.gz/;
  
    warn("Can't extract DB name from the file name,
          probably an error in the file format"),
            next unless defined $db_name and $db_name;
  
      # we want to drop the table since restore will rebuild it!
      # force to drop the db without confirmation
    my $drop_command = "$mysql_admin_exec -f drop $db_name";
    system $drop_command;
  
    $drop_command = "$mysql_admin_exec create $db_name";
    system $drop_command;
  
      # build the command and execute it
    my $restore_command = "$gzip_exec -cd $_ | $mysql_exec $db_name";
    system $restore_command;
  }
  
  # now load the update_log file (update the db with the changes since
  # the last dump
  warn("Can't locate $update_log_file"),next unless  -e $update_log_file;
  
  my $restore_command = 
    "$gzip_exec -cd $update_log_file |$mysql_exec";
  system $restore_command;
  
  # rerun the mysql.backup.pl since we have reloaded the dump files
  # and update log , and we must rebuild backups!
  system $mysql_backup_exec;
  
  
  
  1.1                  modperl-site/guide/code/mysql-3.22.30+_backup.pl
  
  Index: mysql-3.22.30+_backup.pl
  ===================================================================
  #!/usr/bin/perl -w
      
  # this script should be run from the crontab every night or in shorter
  # intervals. This scripts does a few things.
  # 1. dump all the tables into a separate dump files (these dump files 
  # are ready for DB restore)
  # 2. backups the last update log file and create a new log file
  
  #This script originates from the perl.apache.org site, but I have adapted it to work
  #properly with the newer versions of MySQL, where the log files are named differently
  #WVW 14/02/2000 w@ba.be
      
  use strict;
  
  my $data_dir = "/var/lib/mysql";
  my $update_log = "$data_dir/central2.001";
  my $dump_dir  = "$data_dir/backup";
  my $gzip_exec = "/bin/gzip";
  my @db_names = qw(mysql besup);
  my $mysql_admin_exec = "/usr/bin/mysqladmin ";
  my $hostname = "central2";
  
  my $password = "babedb";
      
  # convert unix time to date + time
  my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
  my $time  = sprintf("%0.2d:%0.2d:%0.2d",$hour,$min,$sec);
  my $date  = sprintf("%0.2d.%0.2d.%0.4d",++$mon,$mday,$year+1900);
  my $timestamp = "$date.$time";
      
  # dump all the DBs we want to backup
  foreach my $db_name (@db_names) {
    my $dump_file = "$dump_dir/$timestamp.$db_name.dump";
    my $dump_command = "/usr/bin/mysqldump -c -e -l -q --flush-logs -p$password $db_name > $dump_file";
    system $dump_command;
  }
  
  mkdir "$dump_dir/$timestamp.log", 0;
  `mv $data_dir/$hostname.[0-9]* $dump_dir/$timestamp.log`;
      
  # move update log to backup for later restore if needed
  #rename $update_log, "$dump_dir/$timestamp.log" if -e $update_log;
  
  # restart the update log to log to a new file!
  `/usr/bin/mysqladmin refresh -p$password`;
  
  # compress all the created files
  system "$gzip_exec $dump_dir/$timestamp.log/*";
  system "$gzip_exec $dump_dir/$timestamp.*.dump*";
  
  
  
  1.1                  modperl-site/guide/code/mysql-3.22.30+_restore.pl
  
  Index: mysql-3.22.30+_restore.pl
  ===================================================================
  #!/usr/bin/perl -w
      
  # this scripts restores the DBs
      
  # Usage: mysql.restore.pl update.log.gz dump.db1.gz [... dump.dbn.gz]
  # all files dump* are compressed as we expect them to be created by 
  # mysql.backup utility
      
  # example: 
  # % mysql.restore.pl myhostname.log.gz 12.10.1998.16:37:12.*.dump.gz
      
  # .dump.gz extension.
      
  use strict;
      
  use FindBin qw($Bin);
      
  my $data_dir   = "/var/lib/mysql";
  my $dump_dir   = "$data_dir/backup";
  my $gzip_exec  = "/bin/gzip";
  my $mysql_exec = "/usr/bin/mysql -f -pbabedb";
  my $mysql_backup_exec = "$Bin/mysql_backup.pl";
  my $mysql_admin_exec  = "/usr/bin/mysqladmin -pbabedb";
      
  my $update_log_dir = '';
  my @dump_files = ();
      
  # split input files into an update log and the dump files
  foreach (@ARGV) {
    push(@dump_files, $_),next unless /\.log/;
    $update_log_dir = $_;
  }
      
  die "Usage: mysql.restore.pl update.log.dir dump.db1.gz [... dump.dbn.gz]\n" 
    unless defined @dump_files and @dump_files > 0;
      
  # load the dump files
  foreach (@dump_files) {
      
    # check the file exists
    warn("Can't locate $_"),next unless -e $_;
      
    # extract the db name from the dump file
    my $db_name = $1 if /\d\d\.\d\d.\d\d\d\d.\d\d:\d\d:\d\d\.(\w+)\.dump\.gz/;
      
    warn("Can't extract DB name from the file name,
          probably an error in the file format"),
          next unless defined $db_name and $db_name;
      
    # we want to drop the table since restore will rebuild it!
    # force to drop the db without confirmation
    my $drop_command = "$mysql_admin_exec -f drop $db_name";
    system $drop_command;
      
    $drop_command = "$mysql_admin_exec create $db_name";
    system $drop_command;
      
    # build the command and execute it
    my $restore_command = "$gzip_exec -cd $_ | $mysql_exec $db_name";
    system $restore_command;
  }
      
  # now load the update_log file (update the db with the changes since
  # the last dump
  warn("Can't locate $update_log_dir"),next unless  -d $update_log_dir;
      
  my $restore_command = 
    "$gzip_exec -cd $update_log_dir/* |$mysql_exec";
  system $restore_command;
      
  # rerun the mysql.backup.pl since we have reloaded the dump files
  # and update log , and we must rebuild backups!
  system $mysql_backup_exec;
  
  
  

Mime
View raw message