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; |