File Coverage

blib/lib/IPC/ConcurrencyLimit/WithStandby.pm
Criterion Covered Total %
statement 63 77 81.8
branch 18 28 64.2
condition 1 7 14.2
subroutine 10 13 76.9
pod 0 6 0.0
total 92 131 70.2


line stmt bran cond sub pod time code
1             package IPC::ConcurrencyLimit::WithStandby;
2 3     3   46794 use 5.008001;
  3         6  
3 3     3   9 use strict;
  3         3  
  3         42  
4 3     3   6 use warnings;
  3         3  
  3         87  
5              
6             our $VERSION = '0.16';
7 3     3   9 use Carp qw(croak);
  3         3  
  3         96  
8 3     3   1386 use Time::HiRes qw(sleep);
  3         2889  
  3         9  
9 3     3   1263 use IPC::ConcurrencyLimit;
  3         6  
  3         1455  
10              
11             sub new {
12 8     8 0 104521 my $class = shift;
13 8         61 my %params = @_;
14 8         19 my $type = delete $params{type};
15 8 50       46 $type = 'Flock' if not defined $type;
16              
17 8   33     55 my $standby_type = delete($params{standby_type}) || $type;
18              
19 8         29 foreach my $t ($type, $standby_type) {
20 16         36 my $lock_class = "IPC::ConcurrencyLimit::Lock::$t";
21 16 50       1223 if (not eval "require $lock_class; 1;") {
22 0   0     0 my $err = $@ || 'Zombie error';
23 0         0 croak("Invalid lock type '$t'. Could not load lock class '$lock_class': $err");
24             }
25             }
26              
27 8         9 my %standby;
28 8         70 foreach my $key (grep /^standby_/, keys %params) {
29 10         15 my $munged = $key;
30 10         27 $munged =~ s/^standby_//;
31 10         22 $standby{$munged} = delete $params{$key};
32             }
33 8         51 $standby{$_} = $params{$_} for grep !exists($standby{$_}), keys %params;
34              
35 8         58 my $main_lock = IPC::ConcurrencyLimit->new(%params, type => $type);
36 8         24 my $standby_lock = IPC::ConcurrencyLimit->new(%standby, type => $standby_type);
37              
38             my $self = bless({
39             main_lock => $main_lock,
40             standby_lock => $standby_lock,
41             retries => defined($params{retries}) ? $params{retries} : 10,
42             interval => defined($params{interval}) ? $params{interval} : 1,
43             process_name_change => $params{process_name_change},
44 8 50       62 } => $class);
    50          
45              
46 8         30 return $self;
47             }
48              
49             sub get_lock {
50 10     10 0 1918 my $self = shift;
51 10         19 my $main_lock = $self->{main_lock};
52              
53             # Convert retries to a sub if it's not one already
54 10 100       33 if ( ref $self->{retries} ne "CODE" ) {
55 6         6 my $max_retries = $self->{retries};
56 6     41   21 $self->{retries} = sub { return $_[0] <= $max_retries };
  41         81  
57             }
58              
59 10         37 my $id = $main_lock->get_lock;
60 10 100       24 return $id if defined $id;
61              
62 6         10 my $st_lock = $self->{standby_lock};
63 6         12 my $st_id = $st_lock->get_lock;
64 6 50       16 return undef if not defined $st_id;
65              
66             # got standby lock, go into wait-retry loop
67 6         10 my $old_proc_name;
68 6 50       14 if ($self->{process_name_change}) {
69 0         0 $old_proc_name = $0;
70 0         0 $0 = "$0 - standby";
71             }
72 6         7 my $interval = $self->{interval};
73             eval {
74 6         17 my $tries = 0;
75 6         6 while (1) {
76 322         3757 $id = $main_lock->get_lock;
77 322 100       788 if (defined $id) {
78 3         191 $st_lock->release_lock;
79 3         5 last;
80             }
81              
82 319 100       1900 last unless $self->{retries}->(++$tries);
83 316 100       6817534 sleep($interval) if $interval;
84             }
85 6         23 1;
86             }
87 6 50       37 or do {
88 0   0     0 my $err = $@ || 'Zombie error';
89 0 0       0 $0 = $old_proc_name if defined $old_proc_name;
90 0         0 $st_lock->release_lock;
91 0         0 die $err;
92             };
93              
94 6 50       13 $0 = $old_proc_name if defined $old_proc_name;
95 6         23 return $id;
96             }
97              
98             sub is_locked {
99 0     0 0 0 my $self = shift;
100 0         0 return $self->{main_lock}->is_locked(@_);
101             }
102              
103             sub release_lock {
104 4     4 0 5003080 my $self = shift;
105 4         87 return $self->{main_lock}->release_lock(@_);
106             }
107              
108             sub lock_id {
109 0     0 0   my $self = shift;
110 0           return $self->{main_lock}->lock_id(@_);
111             }
112              
113             sub heartbeat {
114 0     0 0   my $self = shift;
115 0           return $self->{main_lock}->heartbeat;
116             }
117              
118             1;
119              
120             __END__