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   998579 use warnings;
  16         24  
  16         481  
4 16     16   56 use strict;
  16         20  
  16         271  
5 16     16   56 use Carp;
  16         17  
  16         936  
6              
7             our $VERSION = 'v2.3.7';
8              
9 16     16   6232 use Export::Attrs;
  16         90938  
  16         90  
10 16     16   2438 use Narada;
  16         24  
  16         362  
11 16     16   59 use Fcntl qw( :DEFAULT :flock F_SETFD FD_CLOEXEC );
  16         57  
  16         5594  
12 16     16   891 use Errno;
  16         1881  
  16         557  
13 16     16   1024 use Time::HiRes qw( sleep );
  16         2533  
  16         121  
14              
15              
16 16   100 16   1903 use constant IS_NARADA1 => eval { local $SIG{__DIE__}; Narada::detect('narada-1') } || undef;
  16         19  
  16         21  
17 16     16   72 use constant DIR => IS_NARADA1 ? 'var/' : q{};
  16         19  
  16         702  
18 16     16   53 use constant LOCKNEW => DIR.'.lock.new';
  16         17  
  16         736  
19 16     16   50 use constant LOCKFILE => DIR.'.lock';
  16         17  
  16         610  
20 16     16   70 use constant TICK => 0.1;
  16         14  
  16         2628  
21              
22             my $F_lock;
23              
24              
25             sub shared_lock :Export {
26 22     22 1 49 my $timeout = shift;
27 22 50       103 return 1 if $ENV{NARADA_SKIP_LOCK};
28 22 50       777 sysopen $F_lock, LOCKFILE, O_RDONLY|O_CREAT or croak "open: $!";
29 22         58 while (1) {
30 22 50       338 next if -e LOCKNEW;
31 22 50       199 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         63 return 1;
38 16     16   73 }
  16         19  
  16         87  
39              
40             sub exclusive_lock :Export {
41 28 50   28 1 114 return if $ENV{NARADA_SKIP_LOCK};
42 28 50       808 sysopen $F_lock, LOCKFILE, O_WRONLY|O_CREAT or croak "open: $!";
43 28         47 while (1) {
44 28 50       191 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       70337 system('touch', LOCKNEW) == 0 or croak "touch: $!/$?";
50 28         368 return;
51 16     16   4897 }
  16         24  
  16         47  
52              
53             sub unlock_new :Export {
54 22 50   22 1 131 return if $ENV{NARADA_SKIP_LOCK};
55 22         940 unlink LOCKNEW;
56 22         72 return;
57 16     16   2754 }
  16         20  
  16         46  
58              
59             sub unlock :Export {
60 22 50   22 1 94 return if $ENV{NARADA_SKIP_LOCK};
61 22 50       75 if ($F_lock) {
62 22 50       149 flock $F_lock, LOCK_UN or croak "flock: $!";
63             }
64 22         44 return;
65 16     16   3056 }
  16         27  
  16         50  
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   3312 }
  16         19  
  16         46  
75              
76              
77             1; # Magic true value required at end of module
78             __END__