Apache2-ClickPath
view release on metacpan or search on metacpan
lib/Apache2/ClickPath/Store.pm view on Meta::CPAN
return;
}
sub cleanup {
my ($c, $cfg)=@{$_[0]};
my $d=$cfg->{"ClickPathStoreDirectory"};
my $tmout=$cfg->{"ClickPathStoreTimeout"};
my $interval=$cfg->{"ClickPathStoreCleanupInterval"}||$cleanupdefault;
my $time=time;
unless( -f "$d/#lastcleanup" ) {
open my $f, ">$d/#lastcleanup"
or do {
$c->base_server->log->error('['.__PACKAGE__."] Cannot create $d/#lastcleanup: $!");
return;
};
undef $f;
}
open my $f, "<$d/#lastcleanup"
or do {
$c->base_server->log->error('['.__PACKAGE__."] Cannot open $d/#lastcleanup: $!");
return;
};
flock $f, LOCK_EX|LOCK_NB or return; # another cleanup is running
my $lasttime=(stat "$d/#lastcleanup")[9];
if( $time-$lasttime>$interval ) {
utime $time, $time, "$d/#lastcleanup";
opendir my $D, $d
or do {
$c->base_server->log->error('['.__PACKAGE__."] Cannot opendir $d: $!");
return;
};
my @l=readdir $D;
closedir $D;
$c->base_server->log->debug("Cleaning up $d");
foreach my $el (@l) {
next if( $el=~/^\.\.?$/ ); # skip . and ..
next if( $el eq '#lastcleanup' );
# cleanup is done in 2 stages. At first the directory name is
# prepended a hash sign (#) and another cleanup interval
# is waited to let pending requests be served. Then at stage 2 the
# directory is removed.
if( $time-(stat $d.'/'.$el)[9]>$tmout ) {
if( $el=~/^#/ ) {
# stage 2
$c->base_server->log->info('['.__PACKAGE__."] $d/$el has expired: deleting");
rmtree $d.'/'.$el;
} else {
# stage 1
$c->base_server->log->info('['.__PACKAGE__."] $d/$el has expired: marking for deletion");
rename "$d/$el", "$d/#$el"
or do {
$c->log->error('['.__PACKAGE__."] Cannot rename $d/$el to $d/#$el: $! -- deleting $el");
rmtree $d.'/'.$el;
};
}
}
}
}
}
sub handler {
my $r=shift;
my $restorecwd=Perl::AtEndOfScope->new( sub{chdir shift}, Cwd::getcwd );
my $cfg=Apache2::Module::get_config( __PACKAGE__, $r->server );
my $d=$cfg->{"ClickPathStoreDirectory"};
if( $cfg->{"ClickPathStoreTimeout"} ) {
# Call cleanup at the end of a connection. So keep-alive requests
# are served at full speed.
$r->connection->pool->cleanup_register( \&cleanup, [$r->connection, $cfg] )
unless( $r->connection->keepalives );
}
my ($what, $session, $k, $v, $param);
if( $r->main and # is subreq
$param=$r->pnotes( 'Apache2::ClickPath::StoreClient::storeparams' ) ) {
($what, $session, $k, $v)=@{$param}{qw{a s k v}};
} else {
$CGI::Q=CGI->new( $r );
$what=CGI::param( 'a' );
$session=CGI::param( 's' );
$k=CGI::param( 'k' );
$v=CGI::param( 'v' );
}
$d.='/'.$session;
$session=~m!^[^/]+$! or return Apache2::Const::HTTP_BAD_REQUEST;
$k=~m!^\w+$! or return Apache2::Const::HTTP_BAD_REQUEST;
my $time=time;
if( $what eq 'set' ) {
unless( chdir $d ) {
mkdir $d or do {
$r->log->error( '['.__PACKAGE__."] Cannot create directory $d: $!" );
return Apache2::Const::SERVER_ERROR;
};
chdir $d or do {
$r->log->error( '['.__PACKAGE__."] Cannot chdir to $d: $!" );
return Apache2::Const::SERVER_ERROR;
};
}
utime $time, $time, '.'; # update times to prevent cleanup
open my $f, ">$k" or do {
$r->log->error( '['.__PACKAGE__."] Cannot write $d/$k: $!" );
return Apache2::Const::SERVER_ERROR;
};
print $f $v or do {
$r->log->error( '['.__PACKAGE__."] Cannot write $d/$k: $!" );
( run in 0.634 second using v1.01-cache-2.11-cpan-39bf76dae61 )