File Coverage

blib/lib/Narada/Lock.pm
Criterion Covered Total %
statement 74 85 87.0
branch 12 40 30.0
condition 2 5 40.0
subroutine 22 23 95.6
pod 5 5 100.0
total 115 158 72.7


line stmt bran cond sub pod time code
1             package Narada::Lock;
2              
3 16     16   2152462 use warnings;
  16         134  
  16         568  
4 16     16   86 use strict;
  16         52  
  16         385  
5 16     16   78 use Carp;
  16         44  
  16         1222  
6              
7             our $VERSION = 'v2.3.8';
8              
9 16     16   6624 use Export::Attrs;
  16         93752  
  16         96  
10 16     16   2942 use Narada;
  16         30  
  16         412  
11 16     16   78 use Fcntl qw( :DEFAULT :flock F_SETFD FD_CLOEXEC );
  16         27  
  16         6126  
12 16     16   1012 use Errno;
  16         2661  
  16         627  
13 16     16   1162 use Time::HiRes qw( sleep );
  16         2607  
  16         146  
14              
15              
16 16   100 16   2162 use constant IS_NARADA1 => eval { local $SIG{__DIE__}; Narada::detect('narada-1') } || undef;
  16         29  
  16         25  
17 16     16   97 use constant DIR => IS_NARADA1 ? 'var/' : q{};
  16         28  
  16         846  
18 16     16   87 use constant LOCKNEW => DIR.'.lock.new';
  16         27  
  16         854  
19 16     16   94 use constant LOCKFILE => DIR.'.lock';
  16         29  
  16         682  
20 16     16   76 use constant TICK => 0.1;
  16         26  
  16         3335  
21              
22             my $F_lock;
23              
24              
25             sub shared_lock :Export {
26 22     22 1 92 my $timeout = shift;
27 22 50       133 return 1 if $ENV{NARADA_SKIP_LOCK};
28 22 50       1042 sysopen $F_lock, LOCKFILE, O_RDONLY|O_CREAT or croak "open: $!";
29 22         77 while (1) {
30 22 50       336 next if -e LOCKNEW;
31 22 50       285 last if flock $F_lock, LOCK_SH|LOCK_NB;
32 0 0       0 $!{EWOULDBLOCK} or croak "flock: $!";
33             } continue {
34 0 0 0     0 return if defined $timeout and (($timeout-=TICK) < TICK);
35 0         0 sleep TICK;
36             }
37 22         97 return 1;
38 16     16   324 }
  16         40  
  16         118  
39              
40             sub exclusive_lock :Export {
41 28 50   28 1 179 return if $ENV{NARADA_SKIP_LOCK};
42 28 50       1130 sysopen $F_lock, LOCKFILE, O_WRONLY|O_CREAT or croak "open: $!";
43 28         115 while (1) {
44 28 50       327 last if flock $F_lock, LOCK_EX|LOCK_NB;
45 0 0       0 $!{EWOULDBLOCK} or croak "flock: $!";
46 0 0       0 system('touch', LOCKNEW) == 0 or croak "touch: $!/$?";
47 0         0 sleep TICK;
48             }
49 28 50       75202 system('touch', LOCKNEW) == 0 or croak "touch: $!/$?";
50 28         905 return;
51 16     16   6232 }
  16         29  
  16         123  
52              
53             sub unlock_new :Export {
54 22 50   22 1 183 return if $ENV{NARADA_SKIP_LOCK};
55 22         886 unlink LOCKNEW;
56 22         110 return;
57 16     16   3717 }
  16         33  
  16         77  
58              
59             sub unlock :Export {
60 22 50   22 1 115 return if $ENV{NARADA_SKIP_LOCK};
61 22 50       112 if ($F_lock) {
62 22 50       263 flock $F_lock, LOCK_UN or croak "flock: $!";
63             }
64 22         79 return;
65 16     16   4095 }
  16         71  
  16         68  
66              
67             sub child_inherit_lock :Export {
68 0     0 1   my ($is_inherit) = @_;
69 0 0         return if $ENV{NARADA_SKIP_LOCK};
70 0 0         if ($F_lock) {
71 0 0         fcntl $F_lock, F_SETFD, $is_inherit ? 0 : FD_CLOEXEC or croak "fcntl: $!";
    0          
72             }
73 0           return;
74 16     16   4309 }
  16         41  
  16         57  
75              
76              
77             1; # Magic true value required at end of module
78             __END__