File Coverage

blib/lib/IPC/ConcurrencyLimit/Lock/Flock.pm
Criterion Covered Total %
statement 61 64 95.3
branch 19 24 79.1
condition 2 2 100.0
subroutine 12 14 85.7
pod 3 3 100.0
total 97 107 90.6


line stmt bran cond sub pod time code
1             package IPC::ConcurrencyLimit::Lock::Flock;
2 41     41   1431 use 5.008001;
  41         82  
3 41     41   126 use strict;
  41         40  
  41         820  
4 41     41   157 use warnings;
  41         6  
  41         1088  
5 41     41   119 use Carp qw(croak);
  41         42  
  41         1913  
6 41     41   158 use File::Path qw();
  41         6  
  41         471  
7 41     41   159 use File::Spec;
  41         41  
  41         779  
8 41     41   119 use Fcntl qw(:DEFAULT :flock);
  41         40  
  41         16369  
9 41     41   19303 use IO::File ();
  41         35424  
  41         1109  
10              
11             our $VERSION = '0.16';
12 41     41   13582 use IPC::ConcurrencyLimit::Lock;
  41         43  
  41         17391  
13             our @ISA = qw(IPC::ConcurrencyLimit::Lock);
14              
15             sub new {
16 1032     1032 1 1436 my $class = shift;
17 1032         1063 my $opt = shift;
18              
19             my $max_procs = $opt->{max_procs}
20 1032 50       2770 or croak("Need a 'max_procs' parameter");
21             my $path = $opt->{path}
22 1032 50       2422 or croak("Need a 'path' parameter");
23 1032   100     6311 my $lock_mode = lc($opt->{lock_mode} || 'exclusive');
24 1032 50       8382 if ($lock_mode !~ /^(?:exclusive|shared)$/) {
25 0         0 croak("Invalid lock mode '$lock_mode'");
26             }
27 1032 100       3275 my $file_prefix= defined $opt->{file_prefix} ? $opt->{file_prefix} : "";
28 1032 100       2564 $file_prefix .= "." if length $file_prefix;
29 1032 50       2177 my $file_ext= defined $opt->{file_ext} ? $opt->{file_ext} : "lock";
30 1032         4529 $file_ext=~s/^\.?/./;
31              
32 1032         9220 my $self = bless {
33             max_procs => $max_procs,
34             path => $path,
35             lock_fh => undef,
36             lock_file => undef,
37             id => undef,
38             file_prefix => $file_prefix,
39             file_ext => $file_ext,
40             lock_mode => $lock_mode,
41             } => $class;
42              
43 1032 100       2455 $self->_get_lock() or return undef;
44              
45 446         1242 return $self;
46             }
47              
48             sub _get_lock {
49 1032     1032   1088 my $self = shift;
50              
51 1032         112297 File::Path::mkpath($self->{path});
52 1032 100       2506 my $lock_mode_flag = $self->{lock_mode} eq 'shared' ? LOCK_SH : LOCK_EX;
53              
54             # We try in reverse order, so that if a processor is started with
55             # a higher number of allowed locks there is less chance that it starves
56             # a processor with a lower number of allowed locks.
57 1032         1172 my $worker_id = $self->{max_procs};
58 1032         2434 while ($worker_id > 0) {
59 1245         19598 my $lock_file = File::Spec->catfile($self->{path}, join("", $self->{file_prefix}, $worker_id, $self->{file_ext}));
60              
61 1245 50       48386 sysopen(my $fh, $lock_file, O_RDWR|O_CREAT)
62             or die "can't open '$lock_file': $!";
63              
64 1245 100       7365 if (flock($fh, $lock_mode_flag|LOCK_NB)) {
65 446         836 $self->{lock_fh} = $fh;
66 446         1206 seek($fh, 0, 0);
67 446         236161 truncate($fh, 0);
68 446         3790 print $fh $$;
69 446         12740 $fh->flush;
70 446         962 $self->{id} = $worker_id;
71 446         763 $self->{lock_file} = $lock_file;
72 446         883 last;
73             }
74              
75 799         22359 close $fh;
76 799         3974 $worker_id--;
77             }
78              
79 1032 100       5373 return undef if not $self->{id};
80 446         1019 return 1;
81             }
82              
83 0     0 1 0 sub lock_file { $_[0]->{lock_file} }
84 0     0 1 0 sub path { $_[0]->{path} }
85              
86             sub DESTROY {
87 1032     1032   18383999 my $self = shift;
88             # should be superfluous
89 1032 100       15699 close($self->{lock_fh}) if $self->{lock_fh};
90             }
91              
92             1;
93              
94             __END__