mirror of
https://github.com/MariaDB/server.git
synced 2025-07-08 17:02:21 +03:00
137 lines
2.6 KiB
Perl
137 lines
2.6 KiB
Perl
package NDB::Util::Lock;
|
|
|
|
use strict;
|
|
use Carp;
|
|
use Symbol;
|
|
use Fcntl qw(:flock);
|
|
use Errno;
|
|
use File::Basename;
|
|
|
|
require NDB::Util::File;
|
|
|
|
use vars qw(@ISA);
|
|
@ISA = qw(NDB::Util::File);
|
|
|
|
# constructors
|
|
|
|
my $log;
|
|
|
|
sub initmodule {
|
|
$log = NDB::Util::Log->instance;
|
|
}
|
|
|
|
NDB::Util::Lock->attributes(
|
|
pid => sub { $_ != 0 },
|
|
);
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
@_ % 2 == 0 or confess 0+@_;
|
|
my(%attr) = @_;
|
|
my $lock = $class->SUPER::new(%attr);
|
|
return $lock;
|
|
}
|
|
|
|
sub desc {
|
|
my $lock = shift;
|
|
return $lock->getpath;
|
|
}
|
|
|
|
# test / set
|
|
|
|
sub test {
|
|
my $lock = shift;
|
|
@_ == 0 or confess 0+@_;
|
|
my $fh = gensym();
|
|
if (! open($fh, "+<$lock->{path}")) {
|
|
if ($! != Errno::ENOENT) {
|
|
$log->put("$lock->{path}: open failed: $!");
|
|
return undef;
|
|
}
|
|
return 0; # file does not exist
|
|
}
|
|
if (flock($fh, LOCK_EX|LOCK_NB)) {
|
|
close($fh);
|
|
return 0; # file was not locked
|
|
}
|
|
if ($^O eq 'MSWin32') {
|
|
close($fh);
|
|
if (! open($fh, "<$lock->{path}x")) {
|
|
$log->put("$lock->{path}x: open failed: $!");
|
|
return undef;
|
|
}
|
|
}
|
|
my $pid = <$fh>;
|
|
close($fh);
|
|
($pid) = split(' ', $pid);
|
|
if ($pid+0 == 0) {
|
|
$log->put("$lock->{path}: locked but pid='$pid' is zero");
|
|
return undef;
|
|
}
|
|
$lock->{pid} = $pid;
|
|
return 1; # file was locked
|
|
}
|
|
|
|
sub set {
|
|
my $lock = shift;
|
|
@_ == 0 or confess 0+@_;
|
|
my $fh = gensym();
|
|
if (! open($fh, "+<$lock->{path}")) {
|
|
if ($! != Errno::ENOENT) {
|
|
$log->put("$lock->{path}: open failed: $!");
|
|
return undef;
|
|
}
|
|
close($fh);
|
|
if (! open($fh, ">$lock->{path}")) {
|
|
$log->put("$lock->{path}: create failed: $!");
|
|
return undef;
|
|
}
|
|
}
|
|
if (! flock($fh, LOCK_EX|LOCK_NB)) {
|
|
$log->put("$lock->{path}: flock failed: $!");
|
|
close($fh);
|
|
return 0; # file was probably locked
|
|
}
|
|
my $line = "$$\n";
|
|
if ($^O eq 'MSWin32') {
|
|
my $gh = gensym();
|
|
if (! open($gh, ">$lock->{path}x")) {
|
|
$log->put("$lock->{path}x: open for write failed: $!");
|
|
close($fh);
|
|
return undef;
|
|
}
|
|
if (! syswrite($gh, $line)) {
|
|
close($fh);
|
|
close($gh);
|
|
$log->put("$lock->{path}x: write failed: $!");
|
|
return undef;
|
|
}
|
|
close($gh);
|
|
} else {
|
|
if (! truncate($fh, 0)) {
|
|
close($fh);
|
|
$log->put("$lock->{path}: truncate failed: $!");
|
|
return undef;
|
|
}
|
|
if (! syswrite($fh, $line)) {
|
|
close($fh);
|
|
$log->put("$lock->{path}: write failed: $!");
|
|
return undef;
|
|
}
|
|
}
|
|
$lock->{fh} = $fh;
|
|
return 1; # file is now locked by us
|
|
}
|
|
|
|
sub close {
|
|
my $lock = shift;
|
|
@_ == 0 or confess 0+@_;
|
|
my $fh = delete $lock->{fh};
|
|
if ($fh) {
|
|
close($fh);
|
|
}
|
|
}
|
|
|
|
1;
|
|
# vim:set sw=4:
|