| 1 |
wakaba |
1.1 |
package SWE::DB::Lock; |
| 2 |
|
|
use strict; |
| 3 |
wakaba |
1.2 |
|
| 4 |
|
|
my $CurrentlyLocking = {}; |
| 5 |
|
|
my $LockTypes = [qw/ |
| 6 |
|
|
ID Name Index IDs Names Graph Weight Global |
| 7 |
|
|
/]; |
| 8 |
wakaba |
1.4 |
## If you are locking for Graph, then you cannot lock for Global, but |
| 9 |
|
|
## still you can lock for ID. |
| 10 |
wakaba |
1.5 |
## |
| 11 |
|
|
## In addition, if you are locking for an ID, then you can't lock |
| 12 |
|
|
## for another ID. |
| 13 |
|
|
## |
| 14 |
|
|
## XXX Maybe we should get rid of IDs and Name locks because they |
| 15 |
|
|
## conflict with ID and Names locks respectively. Additionally, |
| 16 |
|
|
## maybe we should remove Global lock as well. |
| 17 |
wakaba |
1.4 |
|
| 18 |
|
|
## idgen is currently controled by Names lock. |
| 19 |
wakaba |
1.1 |
|
| 20 |
|
|
use Fcntl ':flock'; |
| 21 |
|
|
|
| 22 |
|
|
sub new ($) { |
| 23 |
|
|
my $self = bless { |
| 24 |
|
|
'file_name' => 'lock', |
| 25 |
wakaba |
1.2 |
lock_type => 'Global', |
| 26 |
wakaba |
1.1 |
}, shift; |
| 27 |
|
|
return $self; |
| 28 |
|
|
} # new |
| 29 |
|
|
|
| 30 |
wakaba |
1.2 |
sub lock_type ($;$) { |
| 31 |
|
|
my $self = shift; |
| 32 |
|
|
if (@_) { |
| 33 |
|
|
$self->{lock_type} = shift; |
| 34 |
|
|
} |
| 35 |
|
|
return $self->{lock_type}; |
| 36 |
|
|
} # lock_type |
| 37 |
|
|
|
| 38 |
|
|
sub check_lockability ($) { |
| 39 |
|
|
my $self = shift; |
| 40 |
|
|
|
| 41 |
|
|
my $self_lt = $self->lock_type; |
| 42 |
|
|
for my $lt (@$LockTypes) { |
| 43 |
wakaba |
1.5 |
if ($CurrentlyLocking->{$lt}) { |
| 44 |
|
|
die qq[$0: It is currently locking for "$lt" so that it cannot be locked for the "$self_lt"]; |
| 45 |
|
|
} elsif ($self_lt eq $lt) { |
| 46 |
wakaba |
1.2 |
last; |
| 47 |
|
|
} |
| 48 |
|
|
} |
| 49 |
|
|
|
| 50 |
|
|
return 1; |
| 51 |
|
|
} # check_lockability |
| 52 |
|
|
|
| 53 |
wakaba |
1.1 |
sub lock ($) { |
| 54 |
|
|
my $self = shift; |
| 55 |
wakaba |
1.2 |
|
| 56 |
|
|
$self->check_lockability; |
| 57 |
|
|
$CurrentlyLocking->{$self->lock_type}++; |
| 58 |
wakaba |
1.5 |
|
| 59 |
|
|
warn "XXX @{[$self->lock_type]} $CurrentlyLocking->{$self->lock_type} $self->{file_name}"; |
| 60 |
wakaba |
1.1 |
|
| 61 |
|
|
open my $file, '>', $self->{file_name} or die "$0: $self->{file_name}: $!"; |
| 62 |
|
|
flock $file, LOCK_EX; |
| 63 |
|
|
$self->{lock} = $file; |
| 64 |
|
|
} # lock |
| 65 |
|
|
|
| 66 |
|
|
sub unlock ($) { |
| 67 |
wakaba |
1.2 |
my $self = shift; |
| 68 |
|
|
|
| 69 |
|
|
$CurrentlyLocking->{$self->lock_type}--; |
| 70 |
|
|
|
| 71 |
|
|
close $self->{lock}; |
| 72 |
wakaba |
1.1 |
} # unlock |
| 73 |
|
|
|
| 74 |
|
|
sub DESTROY ($) { |
| 75 |
|
|
$_[0]->unlock; |
| 76 |
|
|
} # DESTROY |
| 77 |
|
|
|
| 78 |
|
|
1; |