line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package File::VMSVersions;
|
2
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
1508
|
use 5.6.0;
|
|
2
|
|
|
|
|
7
|
|
|
2
|
|
|
|
|
91
|
|
4
|
2
|
|
|
2
|
|
10
|
use strict;
|
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
57
|
|
5
|
2
|
|
|
2
|
|
17
|
use warnings;
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
58
|
|
6
|
|
|
|
|
|
|
|
7
|
2
|
|
|
2
|
|
2491
|
use IO::Handle;
|
|
2
|
|
|
|
|
16101
|
|
|
2
|
|
|
|
|
111
|
|
8
|
2
|
|
|
2
|
|
16
|
use File::Basename;
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
168
|
|
9
|
2
|
|
|
2
|
|
1903
|
use File::Spec::Functions;
|
|
2
|
|
|
|
|
1612
|
|
|
2
|
|
|
|
|
172
|
|
10
|
2
|
|
|
2
|
|
17
|
use Carp;
|
|
2
|
|
|
|
|
4
|
|
|
2
|
|
|
|
|
118
|
|
11
|
2
|
|
|
2
|
|
12
|
use Fcntl qw(:DEFAULT :flock);
|
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
1230
|
|
12
|
2
|
|
|
2
|
|
25401
|
use Data::Dumper;
|
|
2
|
|
|
|
|
17122
|
|
|
2
|
|
|
|
|
4273
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
our $VERSION = '0.1';
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
my $vcfilename = '.vcntl';
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 NAME
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
File::VMSVersions - Perl extension for opening files in a directory with
|
21
|
|
|
|
|
|
|
VMS like versioning
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
use File::VMSVersions;
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my $vdir = File::VMSVersions->new(
|
28
|
|
|
|
|
|
|
-name => "./mydir",
|
29
|
|
|
|
|
|
|
-mode => 'versions',
|
30
|
|
|
|
|
|
|
-limit => 3,
|
31
|
|
|
|
|
|
|
);
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
foreach my $i (1..6) {
|
34
|
|
|
|
|
|
|
my($fh, $fn) = $vdir->open('bla.dat', '>');
|
35
|
|
|
|
|
|
|
die $fn unless $fh;
|
36
|
|
|
|
|
|
|
print $fh "file number $i\n";
|
37
|
|
|
|
|
|
|
print "created $fn\n";
|
38
|
|
|
|
|
|
|
$fh->close;
|
39
|
|
|
|
|
|
|
}
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
Now you should have the following files in ./mydir:
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
.vcntl
|
44
|
|
|
|
|
|
|
bla.dat;lck
|
45
|
|
|
|
|
|
|
bla.dat;4
|
46
|
|
|
|
|
|
|
bla.dat;5
|
47
|
|
|
|
|
|
|
bla.dat;6
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
The B module was developed for maintaining automatic
|
52
|
|
|
|
|
|
|
versioning of files in a directory. When you are using the module's routines for
|
53
|
|
|
|
|
|
|
opening files, it will keep a configurable amount of old versions. The versions
|
54
|
|
|
|
|
|
|
will be identified by a number that is added at the end of the filename after a
|
55
|
|
|
|
|
|
|
semicolon (i. e. F<'myfile.dat;7'>).
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
The configured options for a directory are saved in the file F<'.vcntl'>. They
|
58
|
|
|
|
|
|
|
are read each time the B method is called and written when the B
|
59
|
|
|
|
|
|
|
constructor or the B method are called with according options.
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
F<'.vcntl'> consists of only one line with limit and mode separated by an '#'.
|
62
|
|
|
|
|
|
|
For example:
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
20#days
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
10#versions
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
It is ok to edit F<'.vcntl'> manually
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=cut
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=head1 CONSTRUCTOR
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
To create a new B call the B contructor
|
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
$obj = File::VMSVersions->new(
|
77
|
|
|
|
|
|
|
-name => ,
|
78
|
|
|
|
|
|
|
[ -mode => <'versions'|'days'>,
|
79
|
|
|
|
|
|
|
-limit => , ]
|
80
|
|
|
|
|
|
|
);
|
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
You have to specify both B<-limit> and B<-mode> or none of them. If both
|
83
|
|
|
|
|
|
|
evaluate to false the file F<.vcntl> is read. Otherwise it will be replaced with
|
84
|
|
|
|
|
|
|
the new values. If the file doesn't exist when the configuration is read, there
|
85
|
|
|
|
|
|
|
is no version limit at all.
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=cut
|
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub new {
|
90
|
2
|
|
|
2
|
0
|
1798
|
my($caller) = shift;
|
91
|
2
|
|
33
|
|
|
21
|
my($class) = ref($caller) || $caller;
|
92
|
|
|
|
|
|
|
|
93
|
2
|
|
|
|
|
14
|
my %cfg = @_;
|
94
|
|
|
|
|
|
|
|
95
|
2
|
50
|
|
|
|
10
|
$cfg{-name} or
|
96
|
|
|
|
|
|
|
croak << ' END';
|
97
|
|
|
|
|
|
|
usage: File::VMSVersions->new(
|
98
|
|
|
|
|
|
|
-name => ,
|
99
|
|
|
|
|
|
|
[-mode => <"days"|"versions">,
|
100
|
|
|
|
|
|
|
-limit => ,]
|
101
|
|
|
|
|
|
|
);
|
102
|
|
|
|
|
|
|
END
|
103
|
|
|
|
|
|
|
|
104
|
2
|
50
|
25
|
|
|
20
|
if ($cfg{-mode} xor $cfg{-limit}) {
|
105
|
0
|
0
|
|
|
|
0
|
$cfg{-mode} ?
|
106
|
|
|
|
|
|
|
croak("-limit not specified") :
|
107
|
|
|
|
|
|
|
croak("-mode not specified");
|
108
|
|
|
|
|
|
|
}
|
109
|
|
|
|
|
|
|
|
110
|
2
|
|
|
|
|
11
|
%cfg = _config(%cfg);
|
111
|
|
|
|
|
|
|
|
112
|
2
|
|
|
|
|
12
|
return(bless(\%cfg, $class));
|
113
|
|
|
|
|
|
|
}
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head1 METHODS
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=over 4
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=item B<<< $obj->open( [, |>>']> [, ]) >>>
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
Opens a version of a file. The default mode is '<' (read).
|
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
If version is not specified when reading, the last version will be opened.
|
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
If mode equals '>' (write) or '>>' (append), the specified version of the
|
127
|
|
|
|
|
|
|
desired file will be created or appended (append will create a new file if the
|
128
|
|
|
|
|
|
|
version doesn't exist).
|
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
If there is no version specified, the highest existing version will be
|
131
|
|
|
|
|
|
|
incremented by 1.
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
If the specified version is negative the nth last version will be opened.
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
B returns a list with an indirect filehandle and the filename. On errors
|
136
|
|
|
|
|
|
|
the filehandle is undefined and the filename contains an error message.
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=cut
|
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
sub open {
|
141
|
11
|
|
|
11
|
1
|
3880
|
my($self) = shift;
|
142
|
11
|
|
|
|
|
20
|
my($fn, $mode, $ver) = @_;
|
143
|
|
|
|
|
|
|
|
144
|
11
|
|
50
|
|
|
32
|
$mode ||= '<';
|
145
|
11
|
50
|
|
|
|
54
|
croak("illegal mode '$mode'") unless $mode =~ /^<|>|>>$/;
|
146
|
|
|
|
|
|
|
|
147
|
11
|
|
50
|
|
|
45
|
$ver ||= 0;
|
148
|
|
|
|
|
|
|
|
149
|
11
|
|
|
|
|
59
|
my $fullfn = catfile($self->{-name}, $fn);
|
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
# waiting for lock on lockfile in write mode
|
152
|
11
|
|
|
|
|
15
|
my $lck;
|
153
|
11
|
50
|
|
|
|
34
|
if ($mode =~ />/) {
|
154
|
11
|
|
|
|
|
30
|
$lck = _getlock("$fullfn;lck");
|
155
|
|
|
|
|
|
|
}
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# get version info
|
158
|
11
|
|
|
|
|
32
|
my $info = $self->info($fn);
|
159
|
|
|
|
|
|
|
|
160
|
11
|
|
|
|
|
12
|
my $purge = 0;
|
161
|
|
|
|
|
|
|
|
162
|
11
|
50
|
|
|
|
21
|
if ($mode eq '>') {
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# negative versions in write mode make no sense
|
165
|
|
|
|
|
|
|
# increase version anyway (like VMS)
|
166
|
11
|
50
|
|
|
|
35
|
$ver = $info->{max} + 1 if $ver <= 0;
|
167
|
11
|
|
|
|
|
14
|
$purge = 1;
|
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
} else {
|
170
|
0
|
0
|
|
|
|
0
|
if ($ver) {
|
171
|
0
|
0
|
|
|
|
0
|
if ($ver > 0) {
|
172
|
|
|
|
|
|
|
# ver too small -> set to minimum
|
173
|
0
|
0
|
|
|
|
0
|
$ver = $info->{min} if $ver < $info->{min};
|
174
|
|
|
|
|
|
|
} else {
|
175
|
|
|
|
|
|
|
# get the desired version with negative array index
|
176
|
0
|
|
|
|
|
0
|
$ver = $info->{$self->{-mode}}->[$ver-1];
|
177
|
0
|
0
|
|
|
|
0
|
return(undef, "version >>$ver<< not found") unless defined($ver);
|
178
|
|
|
|
|
|
|
}
|
179
|
0
|
0
|
0
|
|
|
0
|
if ( !exists($info->{$ver}) and $mode eq '>>') {
|
180
|
0
|
|
|
|
|
0
|
$purge = 1;
|
181
|
|
|
|
|
|
|
}
|
182
|
|
|
|
|
|
|
} else {
|
183
|
0
|
|
|
|
|
0
|
$ver = $info->{max};
|
184
|
|
|
|
|
|
|
}
|
185
|
|
|
|
|
|
|
}
|
186
|
|
|
|
|
|
|
|
187
|
11
|
50
|
|
|
|
779
|
CORE::open(my $fh, $mode, "$fullfn;$ver") or
|
188
|
|
|
|
|
|
|
return(undef, "error opening $fullfn version $ver in mode $mode, $!");
|
189
|
|
|
|
|
|
|
|
190
|
11
|
50
|
|
|
|
62
|
$self->purge($fn, $self->config()) if $purge;
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
# releasing lock
|
193
|
11
|
50
|
|
|
|
87
|
$lck->close if $lck;
|
194
|
|
|
|
|
|
|
|
195
|
11
|
|
|
|
|
286
|
return($fh, "$fullfn;$ver");
|
196
|
|
|
|
|
|
|
}
|
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=item B<<< $obj->purge(, [-mode => , -limit => ] >>>
|
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
purges the versions of a file to the specified limit. When limit and mode are
|
202
|
|
|
|
|
|
|
not specified all but the last versions are purged. There is no need to call
|
203
|
|
|
|
|
|
|
B for normal versioning.
|
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=cut
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
sub purge {
|
208
|
12
|
|
|
12
|
1
|
895
|
my($self) = shift;
|
209
|
12
|
|
|
|
|
29
|
my($fn, %cfg) = @_;
|
210
|
|
|
|
|
|
|
|
211
|
12
|
50
|
|
|
|
25
|
croak("purge: no filename specified") unless $fn;
|
212
|
|
|
|
|
|
|
|
213
|
12
|
|
|
|
|
66
|
my $fullfn = catfile($self->{-name}, $fn);
|
214
|
|
|
|
|
|
|
|
215
|
12
|
50
|
50
|
|
|
76
|
if ($cfg{-mode} xor $cfg{-limit}) {
|
216
|
0
|
0
|
|
|
|
0
|
$cfg{-mode} ?
|
217
|
|
|
|
|
|
|
croak("-limit not specified") :
|
218
|
|
|
|
|
|
|
croak("-mode not specified");
|
219
|
|
|
|
|
|
|
}
|
220
|
|
|
|
|
|
|
|
221
|
12
|
100
|
|
|
|
36
|
($cfg{-limit}, $cfg{-mode}) = (1, 'versions') unless $cfg{-mode};
|
222
|
|
|
|
|
|
|
|
223
|
12
|
|
|
|
|
28
|
my $info = $self->info($fn);
|
224
|
|
|
|
|
|
|
|
225
|
12
|
|
|
|
|
36
|
print Dumper($info);
|
226
|
12
|
|
|
|
|
12141
|
print Dumper($self);
|
227
|
12
|
|
|
|
|
3380
|
print Dumper(\%cfg);
|
228
|
|
|
|
|
|
|
|
229
|
12
|
|
|
|
|
2656
|
foreach my $v ( @{$info->{$self->{-mode}}} ) {
|
|
12
|
|
|
|
|
48
|
|
230
|
|
|
|
|
|
|
|
231
|
31
|
100
|
|
|
|
71
|
if ($cfg{-mode} eq 'versions') {
|
232
|
|
|
|
|
|
|
|
233
|
10
|
100
|
|
|
|
76
|
last if ( $info->{count} <= $cfg{-limit} );
|
234
|
|
|
|
|
|
|
|
235
|
4
|
50
|
|
|
|
648
|
if ( unlink("$fullfn;$v") ) {
|
236
|
4
|
|
|
|
|
15
|
delete($info->{$v});
|
237
|
|
|
|
|
|
|
} else {
|
238
|
0
|
|
|
|
|
0
|
carp("couldn't purge $fullfn;$v");
|
239
|
|
|
|
|
|
|
}
|
240
|
|
|
|
|
|
|
|
241
|
4
|
|
|
|
|
9
|
$info->{count}--;
|
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
} else {
|
244
|
|
|
|
|
|
|
|
245
|
21
|
100
|
|
|
|
103
|
if ( $info->{$v} - $info->{d_max} > $cfg{-limit} ) {
|
246
|
2
|
50
|
|
|
|
82
|
if ( unlink("$fullfn;$v") ) {
|
247
|
2
|
|
|
|
|
8
|
delete($info->{$v});
|
248
|
|
|
|
|
|
|
} else {
|
249
|
0
|
|
|
|
|
0
|
carp("couldn't purge $fullfn;$v");
|
250
|
|
|
|
|
|
|
}
|
251
|
|
|
|
|
|
|
}
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
}
|
254
|
|
|
|
|
|
|
}
|
255
|
|
|
|
|
|
|
}
|
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=item B<<< $obj->config([-mode => , -limit => ]) >>>
|
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
Sets and/or returns limit and mode of the directory
|
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=cut
|
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub config {
|
265
|
11
|
|
|
11
|
1
|
14
|
my $self = shift;
|
266
|
|
|
|
|
|
|
|
267
|
11
|
|
|
|
|
22
|
my %cfg = @_;
|
268
|
|
|
|
|
|
|
|
269
|
11
|
50
|
25
|
|
|
73
|
if ($cfg{-limit} xor $cfg{-mode}) {
|
270
|
0
|
|
|
|
|
0
|
croak('please specify both -limit and -mode or none of them!');
|
271
|
|
|
|
|
|
|
}
|
272
|
|
|
|
|
|
|
|
273
|
11
|
|
|
|
|
32
|
$cfg{-name} = $self->{-name};
|
274
|
|
|
|
|
|
|
|
275
|
11
|
|
|
|
|
30
|
return(_config(%cfg));
|
276
|
|
|
|
|
|
|
}
|
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
sub _config {
|
280
|
13
|
|
|
13
|
|
28
|
my(%cfg) = @_;
|
281
|
|
|
|
|
|
|
|
282
|
13
|
|
|
|
|
63
|
my $vfn = catfile($cfg{-name}, $vcfilename);
|
283
|
|
|
|
|
|
|
|
284
|
13
|
100
|
|
|
|
42
|
if ( $cfg{-limit} ) {
|
285
|
|
|
|
|
|
|
|
286
|
2
|
50
|
|
|
|
12
|
croak("illegal mode >>$cfg{-mode}<<") unless $cfg{-mode} =~ /^days|versions$/;
|
287
|
2
|
50
|
|
|
|
14
|
croak("illegal limit >>$cfg{-limit}<<") unless $cfg{-limit} =~ /^\d+$/;
|
288
|
|
|
|
|
|
|
|
289
|
2
|
50
|
|
|
|
166
|
CORE::open(my $vfh, ">", $vfn) or croak("could not write $vfn, $!");
|
290
|
2
|
|
|
|
|
20
|
print $vfh join('#', $cfg{-limit}, $cfg{-mode});
|
291
|
2
|
|
|
|
|
31
|
$vfh->close;
|
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
} else {
|
294
|
|
|
|
|
|
|
|
295
|
11
|
50
|
|
|
|
118
|
if ( -f $vfn ) {
|
296
|
11
|
50
|
|
|
|
288
|
CORE::open(my $vfh, "<", $vfn) or croak("couldn't read $vfn, $!");
|
297
|
11
|
|
|
|
|
216
|
( $cfg{-limit}, $cfg{-mode} ) = split(/#/, <$vfh>);
|
298
|
11
|
|
|
|
|
41
|
$vfh->close;
|
299
|
|
|
|
|
|
|
|
300
|
11
|
50
|
|
|
|
191
|
croak("illegal mode >>$cfg{-mode}<< from $vfn")
|
301
|
|
|
|
|
|
|
unless $cfg{-mode} =~ /^days|versions$/;
|
302
|
11
|
50
|
|
|
|
63
|
croak("illegal limit >>$cfg{-limit}<< from $vfn")
|
303
|
|
|
|
|
|
|
unless $cfg{-limit} =~ /^\d+$/;
|
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
} else {
|
306
|
0
|
|
|
|
|
0
|
( $cfg{-limit}, $cfg{-mode} ) = (999999999999999, 'versions');
|
307
|
|
|
|
|
|
|
}
|
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
}
|
310
|
|
|
|
|
|
|
|
311
|
13
|
|
|
|
|
179
|
return(%cfg);
|
312
|
|
|
|
|
|
|
}
|
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=item B<<< $obj->info() >>>
|
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
returns a hashref with version information for
|
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=cut
|
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
sub info {
|
322
|
26
|
|
|
26
|
1
|
1321
|
my($self) = shift;
|
323
|
26
|
|
|
|
|
35
|
my($fn) = @_;
|
324
|
|
|
|
|
|
|
|
325
|
26
|
50
|
|
|
|
45
|
$fn or croak "usage: info()";
|
326
|
|
|
|
|
|
|
|
327
|
26
|
|
|
|
|
112
|
my $fullfn = catfile($self->{-name}, $fn);
|
328
|
|
|
|
|
|
|
|
329
|
26
|
|
|
|
|
36
|
my(%info, @tmp, $ver);
|
330
|
|
|
|
|
|
|
|
331
|
26
|
|
|
|
|
2590
|
foreach my $f (glob("$fullfn;*")) {
|
332
|
96
|
|
|
|
|
224
|
$ver = (split(/;/, $f))[-1];
|
333
|
96
|
100
|
|
|
|
358
|
next unless $ver =~ /^\d+$/;
|
334
|
70
|
|
|
|
|
697
|
$info{$ver} = -M $f;
|
335
|
|
|
|
|
|
|
}
|
336
|
|
|
|
|
|
|
|
337
|
26
|
|
|
|
|
121
|
@tmp = sort {$a <=> $b} keys(%info);
|
|
69
|
|
|
|
|
128
|
|
338
|
26
|
|
|
|
|
67
|
$info{versions} = [@tmp];
|
339
|
26
|
|
|
|
|
62
|
$info{count} = @tmp;
|
340
|
26
|
|
100
|
|
|
72
|
$info{min} = $tmp[0] || 0;
|
341
|
26
|
|
100
|
|
|
82
|
$info{max} = $tmp[-1] || 0;
|
342
|
26
|
|
|
|
|
65
|
@tmp = sort {$info{$b} <=> $info{$a}} grep {/^\d+$/} keys(%info);
|
|
72
|
|
|
|
|
135
|
|
|
174
|
|
|
|
|
373
|
|
343
|
26
|
|
|
|
|
73
|
$info{days} = [@tmp];
|
344
|
26
|
100
|
|
|
|
144
|
$info{d_min} = $tmp[0] ? $info{$tmp[0]} : 0;
|
345
|
26
|
100
|
|
|
|
56
|
$info{d_max} = $tmp[-1] ? $info{$tmp[-1]} : 0;
|
346
|
|
|
|
|
|
|
|
347
|
26
|
|
|
|
|
77
|
return(\%info);
|
348
|
|
|
|
|
|
|
}
|
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
sub _getlock {
|
352
|
11
|
|
|
11
|
|
15
|
my($fn) = @_;
|
353
|
|
|
|
|
|
|
|
354
|
11
|
100
|
|
|
|
170
|
my $mode = -e $fn ? '<' : '>';
|
355
|
11
|
50
|
|
|
|
420
|
CORE::open(my $lck, $mode, $fn) or croak "couldn't open lock file $fn, $!";
|
356
|
|
|
|
|
|
|
|
357
|
11
|
50
|
|
|
|
73
|
unless (flock($lck, LOCK_EX | LOCK_NB)) {
|
358
|
0
|
|
|
|
|
0
|
flock($lck, LOCK_EX);
|
359
|
|
|
|
|
|
|
}
|
360
|
|
|
|
|
|
|
|
361
|
11
|
|
|
|
|
42
|
return($lck);
|
362
|
|
|
|
|
|
|
}
|
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
=head1 AUTHOR
|
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
Thomas Kratz, EThomasKratz@web.deE
|
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE
|
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
Copyright 2003 by Thomas Kratz
|
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify
|
374
|
|
|
|
|
|
|
it under the same terms as Perl itself.
|
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
=cut
|