File Coverage

perllib/Arch/RunLimit.pm
Criterion Covered Total %
statement 6 56 10.7
branch 0 34 0.0
condition 0 33 0.0
subroutine 2 6 33.3
pod 2 2 100.0
total 10 131 7.6


line stmt bran cond sub pod time code
1             # Arch Perl library, Copyright (C) 2004 Mikhael Goikhman
2             #
3             # This program is free software; you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by
5             # the Free Software Foundation; either version 2 of the License, or
6             # (at your option) any later version.
7             #
8             # This program is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11             # GNU General Public License for more details.
12             #
13             # You should have received a copy of the GNU General Public License
14             # along with this program; if not, write to the Free Software
15             # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16              
17 1     1   27 use 5.005;
  1         3  
  1         36  
18 1     1   5 use strict;
  1         4  
  1         1037  
19              
20             package Arch::RunLimit;
21              
22             sub new ($%) {
23 0     0 1   my $class = shift;
24 0           my %init = @_;
25              
26 0 0 0       my $self = {
    0          
27             limit => exists $init{limit}? $init{limit}: 5,
28             timeout => exists $init{timeout}? $init{timeout}: 30 * 60,
29             file => $init{file} || "/please/specify/run-limit-file",
30             exceeded => undef,
31             added => 0,
32             };
33 0 0 0       $self->{exceeded} = 0 if $self->{limit} <= 0 || $self->{timeout} <= 0;
34              
35 0           bless $self, $class;
36 0           return $self;
37             }
38              
39             sub exceeded ($) {
40 0     0 1   my $self = shift;
41 0 0         return $self->{exceeded} if defined $self->{exceeded};
42              
43 0           my ($hostname, $aliases, $addrtype, $length, $addr) = gethostent();
44 0 0 0       my $hostip = join('.', unpack("C$length", $addr)) if $length && $addr;
45 0   0       $hostname ||= "unknown-host";
46 0   0       $hostip ||= "127.0.0.1";
47 0 0         die "Internal: Unexpected hostname ($hostname)\n" if $hostname =~ /\s/;
48 0 0         die "Internal: Unexpected hostip ($hostip)\n" if $hostip =~ /\s/;
49 0           $self->{host_id} = "$hostname=$hostip";
50              
51 0   0       $self->{proc_able} = -d "/proc" && -d "/proc/$$",
52             $self->{run_id} = "$^T $$ $self->{host_id}\n";
53 0           $self->_update_run_limit_file(1);
54 0           return $self->{exceeded};
55             }
56              
57             sub _update_run_limit_file ($$) {
58 0     0     my $self = shift;
59 0           my $add_self = shift;
60              
61 0 0         return if $self->{exceeded};
62              
63 0           my $file = $self->{file};
64 0 0         unless (-f $file) {
65 0 0         open FH, ">$file" or die "Can't create run-limit file ($file)\n";
66 0           close FH;
67             }
68              
69 0 0         open FH, "+<$file" or die "Can't open $file for updating: $!\n";
70 0           flock FH, 2; # wait for exclusive lock
71 0           seek FH, 0, 0; # rewind to beginning
72 0           my @content = ; # get current content
73              
74 0 0 0       print STDERR map { "run limit old: $_" } @content
  0            
75             if $ENV{DEBUG} && ("$ENV{DEBUG}" & "\2") ne "\0";
76              
77 0 0 0       @content = grep {
      0        
      0        
78 0           /^(\d+) (\d+) ([^\s]+)\n/ && (
79             $3 ne $self->{host_id} || time() - $1 < $self->{timeout} &&
80             (!$self->{proc_able} || -d "/proc/$2")
81             );
82             } @content;
83              
84 0 0         if ($add_self) {
85 0 0         if (@content >= $self->{limit}) {
86 0           $self->{exceeded} = 1;
87             } else {
88 0           $self->{exceeded} = 0;
89 0           $self->{added} = 1;
90 0           push @content, $self->{run_id};
91             }
92             } else {
93 0           @content = grep { $_ ne $self->{run_id} } @content;
  0            
94             }
95              
96 0 0 0       print STDERR map { "run limit new: $_" } @content
  0            
97             if $ENV{DEBUG} && ("$ENV{DEBUG}" & "\2") ne "\0";
98              
99 0           seek FH, 0, 0; # rewind again
100 0           truncate FH, 0; # empty the file
101 0           print FH @content; # print the new content
102 0           close FH; # release file
103             }
104              
105             sub DESTROY ($) {
106 0     0     my $self = shift;
107 0 0 0       return unless $self->{added} && defined $self->{exceeded};
108 0           $self->_update_run_limit_file(0);
109             }
110              
111             1;
112              
113             __END__