--- /dev/null Fri Oct 16 06:02:02 2009
+++ mod_perl-2.0.4/lib/Apache2/Reload.pm Sun Nov 19 15:31:40 2006
@@ -0,0 +1,185 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache2::Reload;
+
+use strict;
+use warnings FATAL => 'all';
+
+use mod_perl2;
+
+our $VERSION = '0.09';
+
+use Apache2::Const -compile => qw(OK);
+
+use Apache2::Connection;
+use Apache2::ServerUtil;
+use Apache2::RequestUtil;
+
+use ModPerl::Util ();
+
+use vars qw(%INCS %Stat $TouchTime);
+
+%Stat = ($INC{"Apache2/Reload.pm"} => time);
+
+$TouchTime = time;
+
+sub import {
+ my $class = shift;
+ my ($package, $file) = (caller)[0,1];
+
+ $class->register_module($package, $file);
+}
+
+sub package_to_module {
+ my $package = shift;
+ $package =~ s/::/\//g;
+ $package .= ".pm";
+ return $package;
+}
+
+sub module_to_package {
+ my $module = shift;
+ $module =~ s/\//::/g;
+ $module =~ s/\.pm$//g;
+ return $module;
+}
+
+sub register_module {
+ my ($class, $package, $file) = @_;
+ my $module = package_to_module($package);
+
+ if ($file) {
+ $INCS{$module} = $file;
+ }
+ else {
+ $file = $INC{$module};
+ return unless $file;
+ $INCS{$module} = $file;
+ }
+}
+
+sub unregister_module {
+ my ($class, $package) = @_;
+ my $module = package_to_module($package);
+ delete $INCS{$module};
+}
+
+# the first argument is:
+# $c if invoked as 'PerlPreConnectionHandler'
+# $r if invoked as 'PerlInitHandler'
+sub handler {
+ my $o = shift;
+ $o = $o->base_server if ref($o) eq 'Apache2::Connection';
+
+ my $DEBUG = ref($o) && (lc($o->dir_config("ReloadDebug") || '') eq 'on');
+
+ my $TouchFile = ref($o) && $o->dir_config("ReloadTouchFile");
+
+ my $ConstantRedefineWarnings = ref($o) &&
+ (lc($o->dir_config("ReloadConstantRedefineWarnings") || '') eq 'off')
+ ? 0 : 1;
+
+ my $TouchModules;
+
+ if ($TouchFile) {
+ warn "Checking mtime of $TouchFile\n" if $DEBUG;
+ my $touch_mtime = (stat $TouchFile)[9] || return Apache2::Const::OK;
+ return Apache2::Const::OK unless $touch_mtime > $TouchTime;
+ $TouchTime = $touch_mtime;
+ open my $fh, $TouchFile or die "Can't open '$TouchFile': $!";
+ $TouchModules = <$fh>;
+ chomp $TouchModules if $TouchModules;
+ }
+
+ if (ref($o) && (lc($o->dir_config("ReloadAll") || 'on') eq 'on')) {
+ *Apache2::Reload::INCS = \%INC;
+ }
+ else {
+ *Apache2::Reload::INCS = \%INCS;
+ my $ExtraList =
+ $TouchModules ||
+ (ref($o) && $o->dir_config("ReloadModules")) ||
+ '';
+ my @extra = split /\s+/, $ExtraList;
+ foreach (@extra) {
+ if (/(.*)::\*$/) {
+ my $prefix = $1;
+ $prefix =~ s/::/\//g;
+ foreach my $match (keys %INC) {
+ if ($match =~ /^\Q$prefix\E/) {
+ $Apache2::Reload::INCS{$match} = $INC{$match};
+ }
+ }
+ }
+ else {
+ Apache2::Reload->register_module($_);
+ }
+ }
+ }
+
+ my $ReloadDirs = ref($o) && $o->dir_config("ReloadDirectories");
+ my @watch_dirs = split(/\s+/, $ReloadDirs||'');
+
+ my @changed;
+ foreach my $key (sort { $a cmp $b } keys %Apache2::Reload::INCS) {
+ my $file = $Apache2::Reload::INCS{$key};
+
+ next unless defined $file;
+ next if @watch_dirs && !grep { $file =~ /^$_/ } @watch_dirs;
+ warn "Apache2::Reload: Checking mtime of $key\n" if $DEBUG;
+
+ my $mtime = (stat $file)[9];
+
+ unless (defined($mtime) && $mtime) {
+ for (@INC) {
+ $mtime = (stat "$_/$file")[9];
+ last if defined($mtime) && $mtime;
+ }
+ }
+
+ warn("Apache2::Reload: Can't locate $file\n"), next
+ unless defined $mtime and $mtime;
+
+ unless (defined $Stat{$file}) {
+ $Stat{$file} = $^T;
+ }
+
+ if ($mtime > $Stat{$file}) {
+ push @changed, $key;
+ }
+ $Stat{$file} = $mtime;
+ }
+
+ #First, let's unload all changed modules
+ foreach my $module (@changed) {
+ my $package = module_to_package($module);
+ ModPerl::Util::unload_package($package);
+ }
+
+ #Then, let's reload them all, so that module dependencies can satisfy
+ #themselves in the correct order.
+ foreach my $module (@changed) {
+ my $package = module_to_package($module);
+ require $module;
+ warn("Apache2::Reload: process $$ reloading $package from $module\n")
+ if $DEBUG;
+ }
+
+ return Apache2::Const::OK;
+}
+
+1;
+__END__
--- /dev/null Fri Oct 16 06:02:02 2009
+++ mod_perl-2.0.4/docs/api/Apache2/Reload.pod Sun Nov 19 15:32:13 2006
@@ -1,0 +1,380 @@
+=head1 NAME
+
+Apache2::Reload - Reload Perl Modules when Changed on Disk
+
+=head1 Synopsis
+
+ # Monitor and reload all modules in %INC:
+ # httpd.conf:
+ PerlModule Apache2::Reload
+ PerlInitHandler Apache2::Reload
+
+ # when working with protocols and connection filters
+ # PerlPreConnectionHandler Apache2::Reload
+
+ # Reload groups of modules:
+ # httpd.conf:
+ PerlModule Apache2::Reload
+ PerlInitHandler Apache2::Reload
+ PerlSetVar ReloadAll Off
+ PerlSetVar ReloadModules "ModPerl::* Apache2::*"
+ #PerlSetVar ReloadDebug On
+
+ # Reload a single module from within itself:
+ package My::Apache2::Module;
+ use Apache2::Reload;
+ sub handler { ... }
+ 1;
+
+=head1 Description
+
+C<Apache2::Reload> reloads modules that change on the disk.
+
+When Perl pulls a file via C<require>, it stores the filename in the
+global hash C<%INC>. The next time Perl tries to C<require> the same
+file, it sees the file in C<%INC> and does not reload from disk. This
+module's handler can be configured to iterate over the modules in
+C<%INC> and reload those that have changed on disk or only specific
+modules that have registered themselves with C<Apache2::Reload>. It can
+also do the check for modified modules, when a special touch-file has
+been modified.
+
+Note that C<Apache2::Reload> operates on the current context of
+C<@INC>. Which means, when called as a C<Perl*Handler> it will not
+see C<@INC> paths added or removed by C<ModPerl::Registry> scripts, as
+the value of C<@INC> is saved on server startup and restored to that
+value after each request. In other words, if you want
+C<Apache2::Reload> to work with modules that live in custom C<@INC>
+paths, you should modify C<@INC> when the server is started. Besides,
+C<'use lib'> in the startup script, you can also set the C<PERL5LIB>
+variable in the httpd's environment to include any non-standard 'lib'
+directories that you choose. For example, to accomplish that you can
+include a line:
+
+ PERL5LIB=/home/httpd/perl/extra; export PERL5LIB
+
+in the script that starts Apache. Alternatively, you can set this
+environment variable in I<httpd.conf>:
+
+ PerlSetEnv PERL5LIB /home/httpd/perl/extra
+
+=head2 Monitor All Modules in C<%INC>
+
+To monitor and reload all modules in C<%INC> at the beginning of
+request's processing, simply add the following configuration to your
+I<httpd.conf>:
+
+ PerlModule Apache2::Reload
+ PerlInitHandler Apache2::Reload
+
+When working with connection filters and protocol modules
+C<Apache2::Reload> should be invoked in the pre_connection stage:
+
+ PerlPreConnectionHandler Apache2::Reload
+
+See also the discussion on
+C<L<PerlPreConnectionHandler|docs::2.0::user::handlers::protocols/PerlPreConnectionHandler>>.
+
+=head2 Register Modules Implicitly
+
+To only reload modules that have registered with C<Apache2::Reload>,
+add the following to the I<httpd.conf>:
+
+ PerlModule Apache2::Reload
+ PerlInitHandler Apache2::Reload
+ PerlSetVar ReloadAll Off
+ # ReloadAll defaults to On
+
+Then any modules with the line:
+
+ use Apache2::Reload;
+
+Will be reloaded when they change.
+
+=head2 Register Modules Explicitly
+
+You can also register modules explicitly in your I<httpd.conf> file
+that you want to be reloaded on change:
+
+ PerlModule Apache2::Reload
+ PerlInitHandler Apache2::Reload
+ PerlSetVar ReloadAll Off
+ PerlSetVar ReloadModules "My::Foo My::Bar Foo::Bar::Test"
+
+Note that these are split on whitespace, but the module list B<must>
+be in quotes, otherwise Apache tries to parse the parameter list.
+
+The C<*> wild character can be used to register groups of files under
+the same namespace. For example the setting:
+
+ PerlSetVar ReloadModules "ModPerl::* Apache2::*"
+
+will monitor all modules under the namespaces C<ModPerl::> and
+C<Apache2::>.
+
+=head2 Monitor Only Certain Sub Directories
+
+To reload modules only in certain directories (and their
+subdirectories) add the following to the I<httpd.conf>:
+
+ PerlModule Apache2::Reload
+ PerlInitHandler Apache2::Reload
+ PerlSetVar ReloadDirectories "/tmp/project1 /tmp/project2"
+
+You can further narrow the list of modules to be reloaded from the
+chosen directories with C<ReloadModules> as in:
+
+ PerlModule Apache2::Reload
+ PerlInitHandler Apache2::Reload
+ PerlSetVar ReloadDirectories "/tmp/project1 /tmp/project2"
+ PerlSetVar ReloadAll Off
+ PerlSetVar ReloadModules "MyApache2::*"
+
+In this configuration example only modules from the namespace
+C<MyApache2::> found in the directories I</tmp/project1/> and
+I</tmp/project2/> (and their subdirectories) will be reloaded.
+
+=head2 Special "Touch" File
+
+You can also declare a file, which when gets C<touch(1)>ed, causes the
+reloads to be performed. For example if you set:
+
+ PerlSetVar ReloadTouchFile /tmp/reload_modules
+
+and don't C<touch(1)> the file I</tmp/reload_modules>, the reloads
+won't happen until you go to the command line and type:
+
+ % touch /tmp/reload_modules
+
+When you do that, the modules that have been changed, will be
+magically reloaded on the next request. This option works with any
+mode described before.
+
+=head2 Unregistering a module
+
+In some cases, it might be necessary to explicitely stop reloading
+a module.
+
+ Apache2::Reload->unregister_module('Some::Module');
+
+But be carefull, since unregistering a module in this way will only
+do so for the current interpreter. This feature should be used with
+care.
+
+=head1 Performance Issues
+
+This module is perfectly suited for a development environment. Though
+it's possible that you would like to use it in a production
+environment, since with C<Apache2::Reload> you don't have to restart
+the server in order to reload changed modules during software
+updates. Though this convenience comes at a price:
+
+=over
+
+=item *
+
+If the "touch" file feature is used, C<Apache2::Reload> has to stat(2)
+the touch file on each request, which adds a slight but most likely
+insignificant overhead to response times. Otherwise C<Apache2::Reload>
+will stat(2) each registered module or even worse--all modules in
+C<%INC>, which will significantly slow everything down.
+
+=item *
+
+Once the child process reloads the modules, the memory used by these
+modules is not shared with the parent process anymore. Therefore the
+memory consumption may grow significantly.
+
+=back
+
+Therefore doing a full server stop and restart is probably a better
+solution.
+
+=head1 Debug
+
+If you aren't sure whether the modules that are supposed to be
+reloaded, are actually getting reloaded, turn the debug mode on:
+
+ PerlSetVar ReloadDebug On
+
+=head1 Caveats
+
+=head2 Problems With Reloading Modules Which Do Not Declare Their Package Name
+
+If you modify modules, which don't declare their C<package>, and rely on
+C<Apache2::Reload> to reload them, you may encounter problems: i.e.,
+it'll appear as if the module wasn't reloaded when in fact it
+was. This happens because when C<Apache2::Reload> C<require()>s such a
+module all the global symbols end up in the C<Apache2::Reload>
+namespace! So the module does get reloaded and you see the compile
+time errors if there are any, but the symbols don't get imported to
+the right namespace. Therefore the old version of the code is running.
+
+
+=head2 Failing to Find a File to Reload
+
+C<Apache2::Reload> uses C<%INC> to find the files on the filesystem. If
+an entry for a certain filepath in C<%INC> is relative,
+C<Apache2::Reload> will use C<@INC> to try to resolve that relative
+path. Now remember that mod_perl freezes the value of C<@INC> at the
+server startup, and you can modify it only for the duration of one
+request when you need to load some module which is not in on of the
+C<@INC> directories. So a module gets loaded, and registered in
+C<%INC> with a relative path. Now when C<Apache2::Reload> tries to find
+that module to check whether it has been modified, it can't find since
+its directory is not in C<@INC>. So C<Apache2::Reload> will silently
+skip that module.
+
+You can enable the C<Debug|/Debug> mode to see what C<Apache2::Reload>
+does behind the scenes.
+
+
+
+=head2 Problems with Scripts Running with Registry Handlers that Cache the Code
+
+The following problem is relevant only to registry handlers that cache
+the compiled script. For example it concerns
+C<L<ModPerl::Registry|docs::2.0::api::ModPerl::Registry>> but not
+C<L<ModPerl::PerlRun|docs::2.0::api::ModPerl::PerlRun>>.
+
+=head3 The Problem
+
+Let's say that there is a module C<My::Utils>:
+
+ #file:My/Utils.pm
+ #----------------
+ package My::Utils;
+ BEGIN { warn __PACKAGE__ , " was reloaded\n" }
+ use base qw(Exporter);
+ @EXPORT = qw(colour);
+ sub colour { "white" }
+ 1;
+
+And a registry script F<test.pl>:
+
+ #file:test.pl
+ #------------
+ use My::Utils;
+ print "Content-type: text/plain\n\n";
+ print "the color is " . colour();
+
+Assuming that the server is running in a single mode, we request the
+script for the first time and we get the response:
+
+ the color is white
+
+Now we change F<My/Utils.pm>:
+
+ - sub colour { "white" }
+ + sub colour { "red" }
+
+And issue the request again. C<Apache2::Reload> does its job and we can
+see that C<My::Utils> was reloaded (look in the I<error_log>
+file). However the script still returns:
+
+ the color is white
+
+=head3 The Explanation
+
+Even though F<My/Utils.pm> was reloaded, C<ModPerl::Registry>'s cached
+code won't run 'C<use My::Utils;>' again (since it happens only once,
+i.e. during the compile time). Therefore the script doesn't know that
+the subroutine reference has been changed.
+
+This is easy to verify. Let's change the script to be:
+
+ #file:test.pl
+ #------------
+ use My::Utils;
+ print "Content-type: text/plain\n\n";
+ my $sub_int = \&colour;
+ my $sub_ext = \&My::Utils::colour;
+ print "int $sub_int\n";
+ print "ext $sub_ext\n";
+
+Issue a request, you will see something similar to:
+
+ int CODE(0x8510af8)
+ ext CODE(0x8510af8)
+
+As you can see both point to the same CODE reference (meaning that
+it's the same symbol). After modifying F<My/Utils.pm> again:
+
+ - sub colour { "red" }
+ + sub colour { "blue" }
+
+and calling the script on the secondnd time, we get:
+
+ int CODE(0x8510af8)
+ ext CODE(0x851112c)
+
+You can see that the internal CODE reference is not the same as the
+external one.
+
+=head3 The Solution
+
+There are two solutions to this problem:
+
+Solution 1: replace C<use()> with an explicit C<require()> +
+C<import()>.
+
+ - use My::Utils;
+ + require My::Utils; My::Utils->import();
+
+now the changed functions will be reimported on every request.
+
+Solution 2: remember to touch the script itself every time you change
+the module that it requires.
+
+=head1 Threaded MPM and Multiple Perl Interpreters
+
+If you use C<Apache2::Reload> with a threaded MPM and multiple Perl
+interpreters, the modules will be reloaded by each interpreter as they
+are used, not every interpreters at once. Similar to mod_perl 1.0
+where each child has its own Perl interpreter, the modules are
+reloaded as each child is hit with a request.
+
+If a module is loaded at startup, the syntax tree of each subroutine
+is shared between interpreters (big win), but each subroutine has its
+own padlist (where lexical my variables are stored). Once
+C<Apache2::Reload> reloads a module, this sharing goes away and each
+Perl interpreter will have its own copy of the syntax tree for the
+reloaded subroutines.
+
+
+=head1 Pseudo-hashes
+
+The short summary of this is: Don't use pseudo-hashes. They are
+deprecated since Perl 5.8 and are removed in 5.9.
+
+Use an array with constant indexes. Its faster in the general case,
+its more guaranteed, and generally, it works.
+
+The long summary is that some work has been done to get this module
+working with modules that use pseudo-hashes, but it's still broken in
+the case of a single module that contains multiple packages that all
+use pseudo-hashes.
+
+So don't do that.
+
+
+
+
+=head1 Copyright
+
+mod_perl 2.0 and its core modules are copyrighted under
+The Apache Software License, Version 2.0.
+
+
+=head1 Authors
+
+Matt Sergeant, matt@sergeant.org
+
+Stas Bekman (porting to mod_perl 2.0)
+
+A few concepts borrowed from C<Stonehenge::Reload> by Randal Schwartz
+and C<Apache::StatINC> (mod_perl 1.x) by Doug MacEachern and Ask
+Bjoern Hansen.
+
+=cut
+