Forks-Super
view release on metacpan or search on metacpan
lib/Forks/Super/Sync/Semaphlock.pm view on Meta::CPAN
return;
}
sub _touch {
my $file = shift;
open my $touch, '>>', $file;
close $touch;
return;
}
sub _releaseAfterFork {
my $self = shift;
# for this implementation, it is more like acquire after fork
my $label = $$ == $self->{ppid} ? 'P' : 'C';
my $wait = time + 5.0;
for my $i (0 .. $self->{count} - 1) {
if ($self->{initial}[$i] eq $label) {
my $file = $self->{files}[$i];
if ($file) {
my $fh;
if (!open $fh, '>>', $file) {
carp 'FS::Sync::Semaphlock::releaseAfterFork: ',
"error acquiring resource $i in $label";
next;
}
flock $fh, 2;
$self->{acquired}[$i] = $fh;
} else {
carp 'FS::Sync::Semaphlock::releaseAfterFork: ',
"no resource $i $file to acquire in $label";
}
}
}
return;
}
sub release {
my ($self, $n) = @_;
return if $n<0 || $n>=$self->{count};
if (defined $self->{acquired}[$n]) {
my $z = flock $self->{acquired}[$n], 8;
$self->{acquired}[$n] = undef;
return $z;
}
return;
}
sub acquire {
my ($self, $n, $timeout) = @_;
return if $n<0 || $n>=$self->{count};
my $file = $self->{files}[$n];
if (defined $self->{acquired}[$n]) {
return -1;
}
my $fh;
# on Cygwin, using fcntl to emulate flock, this open can
# (intermittently) fail with $! := "Device or resource busy"
for my $try (1..5) {
last if open $fh, '>>', $file;
if ($try == 5) {
carp "failed to acquire file resource $file after 5 tries: $!";
return;
}
Time::HiRes::sleep(0.25 * $try);
}
if (defined $timeout) {
my $expire = Time::HiRes::time() + $timeout;
my $z;
do {
$z = flock $fh, 6;
if ($z) {
$self->{acquired}[$n] = $fh;
return $z;
}
if ($timeout > 0.0) {
Time::HiRes::sleep(0.01);
}
} while (Time::HiRes::time() < $expire);
close $fh;
return 0;
}
# no timeout
my $z = flock $fh, 2;
if ($z) {
$self->{acquired}[$n] = $fh;
}
return $z;
}
sub DESTROY {
my $self = shift;
$self->release($_) for 0 .. $self->{count}-1;
$self->{acquired} = [];
unlink @{$self->{unlink}} if $self->{unlink};
$self->{files} = [];
}
sub _get_filename {
no warnings 'once';
# best if this file is not on an NFS filesystem
my @dirs;
if ($^O eq 'MSWin32') {
@dirs = ('C:/Temp', 'C:/Windows/Temp',
'C:/Winnt/Temp', 'D:/Windows/Temp', 'D:/Winnt/Temp',
'E:/Windows/Temp', 'E:/Winnt/Temp', $ENV{TEMP}, '.');
} else {
my ($cwd) = Forks::Super::Util::abs_path('.');
@dirs = ('/dev/shm', '/tmp', '/var/tmp', '/usr/tmp', $cwd);
}
foreach my $dir (@dirs, $Forks::Super::IPC_DIR) {
if ($dir =~ /\S/ && -d $dir && -r $dir && -w $dir && -x $dir) {
return sprintf "%s/_sync%d-%03d",
$dir, $Forks::Super::MAIN_PID || $$, $ipc_seq++;
}
}
( run in 1.644 second using v1.01-cache-2.11-cpan-39bf76dae61 )