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 10     10   1122 use 5.008001;
  10         28  
3 10     10   44 use strict;
  10         11  
  10         241  
4 10     10   41 use warnings;
  10         18  
  10         470  
5 10     10   53 use Carp qw(croak);
  10         13  
  10         735  
6 10     10   61 use File::Path qw();
  10         10  
  10         213  
7 10     10   87 use File::Spec;
  10         14  
  10         275  
8 10     10   36 use Fcntl qw(:DEFAULT :flock);
  10         11  
  10         4613  
9 10     10   6018 use IO::File ();
  10         17856  
  10         420  
10              
11             our $VERSION = '0.17';
12 10     10   4404 use IPC::ConcurrencyLimit::Lock;
  10         21  
  10         6171  
13             our @ISA = qw(IPC::ConcurrencyLimit::Lock);
14              
15             sub new {
16 449     449 1 797 my $class = shift;
17 449         594 my $opt = shift;
18              
19             my $max_procs = $opt->{max_procs}
20 449 50       1725 or croak("Need a 'max_procs' parameter");
21             my $path = $opt->{path}
22 449 50       1299 or croak("Need a 'path' parameter");
23 449   100     2396 my $lock_mode = lc($opt->{lock_mode} || 'exclusive');
24 449 50       3459 if ($lock_mode !~ /^(?:exclusive|shared)$/) {
25 0         0 croak("Invalid lock mode '$lock_mode'");
26             }
27 449 100       1593 my $file_prefix= defined $opt->{file_prefix} ? $opt->{file_prefix} : "";
28 449 100       1275 $file_prefix .= "." if length $file_prefix;
29 449 50       1045 my $file_ext= defined $opt->{file_ext} ? $opt->{file_ext} : "lock";
30 449         2038 $file_ext=~s/^\.?/./;
31              
32 449         4569 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 449 100       1387 $self->_get_lock() or return undef;
44              
45 87         374 return $self;
46             }
47              
48             sub _get_lock {
49 449     449   777 my $self = shift;
50              
51 449         24214 File::Path::mkpath($self->{path});
52 449 100       1729 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 449         737 my $worker_id = $self->{max_procs};
58 449         1308 while ($worker_id > 0) {
59 662         10761 my $lock_file = File::Spec->catfile($self->{path}, join("", $self->{file_prefix}, $worker_id, $self->{file_ext}));
60              
61 662 50       27018 sysopen(my $fh, $lock_file, O_RDWR|O_CREAT)
62             or die "can't open '$lock_file': $!";
63              
64 662 100       4367 if (flock($fh, $lock_mode_flag|LOCK_NB)) {
65 87         188 $self->{lock_fh} = $fh;
66 87         313 seek($fh, 0, 0);
67 87         3471 truncate($fh, 0);
68 87         1098 print $fh $$;
69 87         3070 $fh->flush;
70 87         363 $self->{id} = $worker_id;
71 87         164 $self->{lock_file} = $lock_file;
72 87         235 last;
73             }
74              
75 575         4023 close $fh;
76 575         2609 $worker_id--;
77             }
78              
79 449 100       3155 return undef if not $self->{id};
80 87         280 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 449     449   2224854 my $self = shift;
88             # should be superfluous
89 449 100       6026 close($self->{lock_fh}) if $self->{lock_fh};
90             }
91              
92             1;
93              
94             __END__