File Coverage

blib/lib/File/CounterFile.pm
Criterion Covered Total %
statement 97 103 94.1
branch 30 44 68.1
condition n/a
subroutine 15 16 93.7
pod 0 8 0.0
total 142 171 83.0


line stmt bran cond sub pod time code
1             package File::CounterFile;
2              
3             # $Id: CounterFile.pm,v 0.23 2004/01/23 08:37:18 gisle Exp $
4              
5             require 5.004;
6              
7 1002     1002   5834459 use strict;
  1002         2003  
  1002         41075  
8              
9 1002     1002   5011 use Carp qw(croak);
  1002         2004  
  1002         88155  
10 1002     1002   943925 use Symbol qw(gensym);
  1002         1185314  
  1002         6868938  
11 1002     1002   19026 use Fcntl qw(LOCK_EX O_RDWR O_CREAT);
  1002         3005  
  1002         224334  
12              
13             BEGIN {
14             # older version of Fcntl did not know about SEEK_SET
15 1002 50   1002   8014 if ($] < 5.006) {
16 0         0 *SEEK_SET = sub () { 0 };
17             }
18             else {
19 1002         65115 Fcntl->import("SEEK_SET");
20             }
21             }
22              
23 1002     1002   7013 use vars qw($VERSION $MAGIC $DEFAULT_INITIAL $DEFAULT_DIR);
  1002         3005  
  1002         242502  
24              
25 0     0 0 0 sub Version { $VERSION; }
26             $VERSION = "1.04";
27              
28             $MAGIC = "#COUNTER-1.0\n"; # first line in counter files
29             $DEFAULT_INITIAL = 0; # default initial counter value
30              
31             # default location for counter files
32             $DEFAULT_DIR = $ENV{TMPDIR} || "/usr/tmp";
33              
34             # Experimental overloading.
35 1002         12021 use overload ('++' => \&inc,
36             '--' => \&dec,
37             '""' => \&value,
38             fallback => 1,
39 1002     1002   1949262 );
  1002         1232562  
40              
41              
42             sub new
43             {
44 50607     50607 0 51416563599 my($class, $file, $initial) = @_;
45 50607 50       704560 croak("No file specified\n") unless defined $file;
46              
47 50607 50       1368517 $file = "$DEFAULT_DIR/$file" unless $file =~ /^[\.\/]/;
48 50607 100       274173 $initial = $DEFAULT_INITIAL unless defined $initial;
49              
50 50607         110826 my $value;
51 50607         3368585 local($/, $\) = ("\n", undef);
52 50607         418861 local *F;
53 50607 50       7751835 sysopen(F, $file, O_RDWR|O_CREAT) or croak("Can't open $file: $!");
54 50607 50       4985078 flock(F, LOCK_EX) or croak("Can't flock: $!");
55 50607         3387740 my $first_line = ;
56 50607 100       297826 if (defined $first_line) {
57 50504 50       272279 croak "Bad counter magic '$first_line' in $file" unless $first_line eq $MAGIC;
58 50504         114136 $value = ;
59 50504         406195 chomp($value);
60             }
61             else {
62 103         8105 seek(F, 0, SEEK_SET);
63 103         5172 print F $MAGIC;
64 103         9425 print F "$initial\n";
65 103         3524 $value = $initial;
66             }
67 50607 50       1656668 close(F) || croak("Can't close $file: $!");
68              
69 50607         2266925 bless { file => $file, # the filename for the counter
70             'value' => $value, # the current value
71             updated => 0, # flag indicating if value has changed
72             # handle => XXX, # file handle symbol. Only present when locked
73             };
74             }
75              
76              
77             sub locked
78             {
79 229439     229439 0 1869598 exists shift->{handle};
80             }
81              
82              
83             sub lock
84             {
85 59609     59609 0 159038 my($self) = @_;
86 59609 50       254991 $self->unlock if $self->locked;
87              
88 59609         728626 my $fh = gensym();
89 59609         3434081 my $file = $self->{file};
90              
91 59609 50       5365447 open($fh, "+<$file") or croak "Can't open $file: $!";
92 59609 50       10894494 flock($fh, LOCK_EX) or croak "Can't flock: $!"; # 2 = exlusive lock
93              
94 59609         529619 local($/) = "\n";
95 59609         1279153 my $magic = <$fh>;
96 59609 50       268254 if ($magic ne $MAGIC) {
97 0         0 $self->unlock;
98 0         0 croak("Bad counter magic '$magic' in $file");
99             }
100 59609         209620 chomp($self->{'value'} = <$fh>);
101              
102 59609         473353 $self->{handle} = $fh;
103 59609         303374 $self->{updated} = 0;
104 59609         272520 $self;
105             }
106              
107              
108             sub unlock
109             {
110 110215     110215 0 185373 my($self) = @_;
111 110215 100       308719 return unless $self->locked;
112              
113 59609         204271 my $fh = $self->{handle};
114              
115 59609 100       250534 if ($self->{updated}) {
116             # write back new value
117 10008         52334 local($\) = undef;
118 10008 50       156899 seek($fh, 0, SEEK_SET) or croak "Can't seek to beginning: $!";
119 10008         79753 print $fh $MAGIC;
120 10008         66002 print $fh "$self->{'value'}\n";
121             }
122              
123 59609 50       2652458 close($fh) or warn "Can't close: $!";
124 59609         277509 delete $self->{handle};
125 59609         309104 $self;
126             }
127              
128              
129             sub inc
130             {
131 10010     10010 0 280184 my($self) = @_;
132              
133 10010 100       154396 if ($self->locked) {
134 4         8 $self->{'value'}++;
135 4         8 $self->{updated} = 1;
136             } else {
137 10006         107396 $self->lock;
138 10006         163397 $self->{'value'}++;
139 10006         24980 $self->{updated} = 1;
140 10006         108311 $self->unlock;
141             }
142 10010         159181 $self->{'value'}; # return value
143             }
144              
145              
146             sub dec
147             {
148 3     3 0 10 my($self) = @_;
149              
150 3 100       13 if ($self->locked) {
151 1 50       8 unless ($self->{'value'} =~ /^\d+$/) {
152 0         0 $self->unlock;
153 0         0 croak "Autodecrement is not magical in perl";
154             }
155 1         3 $self->{'value'}--;
156 1         3 $self->{updated} = 1;
157             }
158             else {
159 2         5 $self->lock;
160 2 100       17 unless ($self->{'value'} =~ /^\d+$/) {
161 1         5 $self->unlock;
162 1         242 croak "Autodecrement is not magical in perl";
163             }
164 1         4 $self->{'value'}--;
165 1         3 $self->{updated} = 1;
166 1         3 $self->unlock;
167             }
168 2         7 $self->{'value'}; # return value
169             }
170              
171              
172             sub value
173             {
174 49602     49602 0 601303 my($self) = @_;
175 49602         114631 my $value;
176 49602 100       308316 if ($self->locked) {
177 2         4 $value = $self->{'value'};
178             }
179             else {
180 49600         539733 $self->lock;
181 49600         99203 $value = $self->{'value'};
182 49600         391498 $self->unlock;
183             }
184 49602         316620 $value;
185             }
186              
187              
188             sub DESTROY
189             {
190 50607     50607   48513935 my $self = shift;
191 50607         181046 $self->unlock;
192             }
193              
194             1;
195              
196             __END__