As I mentioned - this code has been running fine in a production server for 18 months or more - the previous code definitely worked.
I'm quite willing to believe there is something else in the environment that is getting in the way - I was just very surprised (and, happily, judging by ppls reactions so far, so are they) that the my() variable wasn't filled in.
And, yes, I've tested that fill_cache gets values and puts them into %cache. The problem is that the values don't hang around once fill_cache() returns. I don't know why :-)
Output from full code below is here. First set of statements is with my(), second with our(). Full apache restart just before each request.
A normal request involves hitting the cache for password then again for a list of allowed groups (in two separate Auth* handlers) and checking against the Apache require group directive. You can see that the group lookup isn't even mentioned on the successful run as it is already cached.
[18981] get_pass: not in cache - retrieving
[18981] fill_cache: setting cache [andrewo] pw:[andrewo] groups:[enabl
+ed]
[18981] get_pass: password now: andrewo
[18981] get_groups: not in cache - retrieving
[18981] fill_cache: setting cache [andrewo] pw:[andrewo] groups:[enabl
+ed]
[18981] get_groups: groups now: user undef!
[Tue Sep 20 17:15:51 2005] [error] Can't use an undefined value as an
+ARRAY reference at
/usr/local/share/perl/5.8.4/Oriel/Apache/UserCache.pm line 56.\n
[19054] get_pass: not in cache - retrieving
[19054] fill_cache: setting cache [andrewo] pw:[andrewo] groups:[enabl
+ed]
[19054] get_pass: password now: andrewo
And the full UserCache module (with added warns):
package My::Apache::UserCache;
use strict;
use Apache::Constants qw(:common);
use My::User;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(get_pass get_groups);
use constant CACHE_TIMEOUT => 60; # seconds
#
# username => { timestamp => unixtime,
# password => blah,
# groups => [groups], },
#
our %cache = ();
sub fill_cache {
my $user = shift;
my $now = time;
my ($password, @groups) = Oriel::User->get_pw_groups($user );
# enforce at least 1 character passwords
return 0 unless defined $password && length($password);
warn "[$$] fill_cache: setting cache [$user] pw:[$password] groups:[
+".join(',',@groups)."]\n";
$cache{$user} = { timestamp => $now,
password => $password,
groups => [@groups] };
}
sub get_pass {
my $user = shift;
my $now = time;
return $cache{$user}->{password}
if ( exists $cache{$user} &&
$cache{$user}->{timestamp} &&
($now - $cache{$user}->{timestamp}) < CACHE_TIMEOUT );
warn "[$$] get_pass: not in cache - retrieving\n";
return undef unless fill_cache( $user );
warn "[$$] get_pass: password now: ".(defined cache{$user} ? $cache{
+$user}->{password} : 'user undef!')."\n";
$cache{$user}->{password};
}
sub get_groups {
my $user = shift;
my $now = time;
return @{$cache{$user}->{groups}}
if ( exists $cache{$user} &&
$cache{$user}->{timestamp} &&
($now - $cache{$user}->{timestamp}) < CACHE_TIMEOUT );
warn "[$$] get_groups: not in cache - retrieving\n";
return () unless fill_cache( $user );
warn "[$$] get_groups: groups now: ".(defined $cache{$user} ? @{$cac
+he{$user}->{groups}} : 'user undef!')."\n";
@{$cache{$user}->{groups}};
}
1;
Its weird. Any ideas? |