Apache-ASP
view release on metacpan or search on metacpan
lib/Apache/ASP/StateManager.pm view on Meta::CPAN
# don't return so we can't delete the empty group later
# return unless scalar(@$ids);
$asp->{dbg} && $asp->Debug("group check $group_id, next in $next_check sec");
my $id = $self->{Session}->SessionID();
my $deleted = 0;
$internal->LOCK();
$asp->{dbg} && $asp->Debug("checking group ids", $ids);
for my $id (@$ids) {
eval {
# if($id eq $_) {
# $asp->{dbg} && $asp->Debug("skipping delete self", {id => $id});
# next;
# }
# we lock the internal, so a session isn't being initialized
# while we are garbage collecting it... we release it every
# time so we don't starve session creation if this is a large
# directory that we are garbage collecting
my $idata = $internal->{$id};
# do this check in case this data is corrupt, and not deserialized, correctly
unless(ref($idata) && (ref($idata) eq 'HASH')) {
$idata = {};
}
my $timeout = $idata->{timeout} || 0;
unless($timeout) {
# we don't have the timeout always, since this session
# may just have been created, just in case this is
# a corrupted session (does this happen still ??), we give it
# a timeout now, so we will be sure to clean it up
# eventualy
$idata->{timeout} = time() + $asp->{session_timeout};
$internal->{$id} = $idata;
$asp->Debug("resetting timeout for $id to $idata->{timeout}");
return; # no next in eval {}
}
# only delete sessions that have timed out
unless($timeout < time()) {
$asp->{dbg} && $asp->Debug("$id not timed out with $timeout");
return; # no next in eval {}
}
# UPDATE & UNLOCK, as soon as we update internal, we may free it
# definately don't lock around SessionOnEnd, as it might take
# a while to process
# set the timeout for this session forward so it won't
# get garbage collected by another process
$asp->{dbg} && $asp->Debug("resetting timeout for deletion lock on $id");
$internal->{$id} = {
%{$internal->{$id}},
'timeout' => time() + $asp->{session_timeout},
'end' => 1,
};
# unlock many times in case we are locked above this loop
for (1..3) { $internal->UNLOCK() }
$asp->{GlobalASA}->SessionOnEnd($id);
$internal->LOCK;
# set up state
my($member_state) = Apache::ASP::State::new($asp, $id);
if(my $count = $member_state->Delete()) {
$asp->{dbg} &&
$asp->Debug("deleting session", {
session_id => $id,
files_deleted => $count,
});
$deleted++;
delete $internal->{$id};
} else {
$asp->Error("can't delete session id: $id");
return; # no next in eval {}
}
};
if($@) {
$asp->Error("error for cleanup of session id $id: $@");
}
}
$internal->UNLOCK();
#### LEAVE DIRECTORIES, NASTY RACE CONDITION POTENTIAL
## NOW PRUNE ONLY DIRECTORIES THAT WE DON'T NEED TO KEEP
## FOR PERFORMANCE
# REMOVE DIRECTORY, LOCK
# if the directory is still empty, remove it, lock it
# down so no new sessions will be created in it while we
# are testing
if($deleted == @$ids) {
if ($state->GroupId !~ /^[0]/) {
$asp->{Internal}->LOCK();
my $ids = $state->GroupMembers();
if(@{$ids} == 0) {
$self->Log("purging stale group ".$state->GroupId.", which should only happen ".
"after Apache::ASP upgrade to beyond 2.09");
$state->DeleteGroupId();
}
$asp->{Internal}->UNLOCK();
}
}
$deleted;
}
sub CleanupGroups {
my($self, $force) = @_;
return unless $self->{Session};
my $cleanup = 0;
my $state_dir = $self->{state_dir};
my $internal = $self->{Internal};
$force ||= 0;
$self->Debug("forcing groups cleanup") if ($self->{dbg} && $force);
# each apache process has an internal time in which it
( run in 0.964 second using v1.01-cache-2.11-cpan-39bf76dae61 )