line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# -*- Mode: Perl -*- |
2
|
|
|
|
|
|
|
# $Basename: Base.pm $ |
3
|
|
|
|
|
|
|
# $Revision: 1.3 $ |
4
|
|
|
|
|
|
|
# Author : Ulrich Pfeifer |
5
|
|
|
|
|
|
|
# Created On : Mon Mar 25 09:58:31 1996 |
6
|
|
|
|
|
|
|
# Last Modified By: Ulrich Pfeifer |
7
|
|
|
|
|
|
|
# Last Modified On: Tue Apr 29 09:08:33 2003 |
8
|
|
|
|
|
|
|
# Language : Perl |
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
# (C) Copyright 1996, Universität Dortmund, all rights reserved. |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
package Logfile::Base; |
14
|
8
|
|
|
8
|
|
40
|
use Carp; |
|
8
|
|
|
|
|
10
|
|
|
8
|
|
|
|
|
788
|
|
15
|
8
|
|
|
8
|
|
36
|
use vars qw($VERSION $nextfh); |
|
8
|
|
|
|
|
11
|
|
|
8
|
|
|
|
|
441
|
|
16
|
8
|
|
|
8
|
|
41
|
use strict; |
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
15753
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# $Format: "$\VERSION = sprintf '%5.3f', ($ProjectMajorVersion$ * 100 + ($ProjectMinorVersion$-1))/1000;"$ |
19
|
|
|
|
|
|
|
$VERSION = sprintf '%5.3f', (2 * 100 + (3-1))/1000; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
$Logfile::MAXWIDTH = 40; |
22
|
|
|
|
|
|
|
my ($HaveParseDate, $HaveGetDate, $HaveDateGetDate); |
23
|
|
|
|
|
|
|
$nextfh = 'fh000'; |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub isafh { |
26
|
8
|
|
|
8
|
0
|
19
|
my $f = shift; |
27
|
8
|
50
|
33
|
|
|
132
|
ref $f eq 'GLOB' |
28
|
|
|
|
|
|
|
or ref \$f eq 'GLOB' |
29
|
|
|
|
|
|
|
or (ref $f) =~ /^IO::/ |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub new { |
33
|
8
|
|
|
8
|
0
|
209
|
my $type = shift; |
34
|
8
|
|
|
|
|
41
|
my %par = @_; |
35
|
8
|
|
|
|
|
22
|
my $self = {}; |
36
|
8
|
|
|
|
|
63
|
my $file = $par{File}; |
37
|
|
|
|
|
|
|
|
38
|
8
|
50
|
|
|
|
41
|
if (ref $par{Group}) { |
39
|
8
|
|
|
|
|
28
|
$self->{Group} = $par{Group}; |
40
|
|
|
|
|
|
|
} else { |
41
|
0
|
|
|
|
|
0
|
$self->{Group} = [$par{Group}]; |
42
|
|
|
|
|
|
|
} |
43
|
8
|
50
|
|
|
|
108
|
if ($file) { |
44
|
8
|
50
|
|
|
|
34
|
if (isafh $file) { |
45
|
0
|
|
|
|
|
0
|
$self->{Fh} = $file; |
46
|
|
|
|
|
|
|
} else { |
47
|
8
|
|
|
|
|
74
|
*S = "${type}::".++$nextfh; |
48
|
8
|
|
|
|
|
35
|
$self->{Fh} = *S; |
49
|
8
|
50
|
|
|
|
43
|
if ($file =~ /\.gz$/) { |
50
|
0
|
0
|
|
|
|
0
|
open(S, "gzip -cd $file|") |
51
|
|
|
|
|
|
|
or die "Could not open $file: $!\n"; |
52
|
|
|
|
|
|
|
} else { |
53
|
8
|
50
|
|
|
|
449
|
open(S, "$file") |
54
|
|
|
|
|
|
|
or die "Could not open $file: $!\n"; |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
} else { |
59
|
0
|
|
|
|
|
0
|
$self->{Fh} = *ARGV; |
60
|
|
|
|
|
|
|
} |
61
|
8
|
|
33
|
|
|
67
|
bless $self, $type || ref($type); |
62
|
8
|
|
|
|
|
72
|
$self->readfile; |
63
|
8
|
100
|
|
|
|
150
|
close S if $self->{File}; |
64
|
8
|
|
|
|
|
47
|
$self; |
65
|
|
|
|
|
|
|
} |
66
|
|
|
|
|
|
|
|
67
|
0
|
|
|
0
|
0
|
0
|
sub norm { $_[2]; } # dummy |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
sub group { |
70
|
1515
|
|
|
1515
|
0
|
1953
|
my ($self, $group) = @_; |
71
|
|
|
|
|
|
|
|
72
|
1515
|
100
|
|
|
|
2670
|
if (ref($group)) { |
73
|
473
|
|
|
|
|
539
|
join $;, @{$group}; |
|
473
|
|
|
|
|
1473
|
|
74
|
|
|
|
|
|
|
} else { |
75
|
1042
|
|
|
|
|
1827
|
$group; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub key { |
80
|
1475
|
|
|
1475
|
0
|
1888
|
my ($self, $group, $rec) = @_; |
81
|
1475
|
|
|
|
|
1834
|
my $key = ''; |
82
|
|
|
|
|
|
|
|
83
|
1475
|
100
|
|
|
|
2350
|
if (ref($group)) { |
84
|
468
|
|
|
|
|
490
|
$key = join $;, map($self->norm($_, $rec->{$_}), @{$group}); |
|
468
|
|
|
|
|
1637
|
|
85
|
|
|
|
|
|
|
} else { |
86
|
1007
|
|
|
|
|
5090
|
$key = $self->norm($group, $rec->{$group}); |
87
|
|
|
|
|
|
|
} |
88
|
1475
|
|
|
|
|
3186
|
$key; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
sub readfile { |
92
|
8
|
|
|
8
|
0
|
17
|
my $self = shift; |
93
|
8
|
|
|
|
|
60
|
my $fh = $self->{Fh}; |
94
|
8
|
|
|
|
|
33
|
my @group = @{$self->{Group}}; |
|
8
|
|
|
|
|
29
|
|
95
|
8
|
|
|
|
|
30
|
my $group; |
96
|
|
|
|
|
|
|
|
97
|
8
|
|
|
|
|
210
|
while (!eof($fh)) { |
98
|
406
|
|
|
|
|
1469
|
my $rec = $self->next; |
99
|
406
|
100
|
|
|
|
943
|
last unless $rec; |
100
|
402
|
|
|
|
|
749
|
for $group (@group) { |
101
|
1475
|
|
|
|
|
3050
|
my $gname = $self->group($group); |
102
|
1475
|
|
|
|
|
3058
|
my $key = $self->key($group, $rec); |
103
|
|
|
|
|
|
|
|
104
|
1475
|
100
|
|
|
|
3686
|
if (defined $self->{$gname}->{$key}) { |
105
|
1089
|
|
|
|
|
3024
|
$self->{$gname}->{$key}->add($rec,$group); # !! |
106
|
|
|
|
|
|
|
} else { |
107
|
386
|
|
|
|
|
832
|
$self->{$gname}->{$key} = $rec->copy; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub report { |
114
|
40
|
|
|
40
|
0
|
347
|
my $self = shift; |
115
|
40
|
|
|
|
|
141
|
my %par = @_; |
116
|
40
|
|
|
|
|
108
|
my $group = $self->group($par{Group}); |
117
|
40
|
|
66
|
|
|
155
|
my $sort = $par{Sort} || $group; |
118
|
40
|
|
75
|
|
|
324
|
my $rever = (($sort =~ /Date|Hour/) xor $par{Reverse}); |
119
|
40
|
|
|
|
|
64
|
my $list = $par{List}; |
120
|
40
|
|
|
|
|
46
|
my ($keys, $key, $val, %keys); |
121
|
40
|
|
|
|
|
58
|
my $mklen = length($group); |
122
|
40
|
100
|
|
|
|
82
|
my $direction = ($rever)?'increasing':'decreasing'; |
123
|
40
|
|
|
|
|
46
|
my (@list, %absolute); |
124
|
40
|
|
|
|
|
370
|
my @mklen = map(length($_), split($;, $group)); |
125
|
|
|
|
|
|
|
|
126
|
40
|
50
|
|
|
|
155
|
croak "No index for $group\n" unless $self->{$group}; |
127
|
|
|
|
|
|
|
|
128
|
40
|
100
|
|
|
|
88
|
if ($list) { |
129
|
19
|
100
|
|
|
|
49
|
if (ref($list)) { |
130
|
17
|
|
|
|
|
21
|
@list = @{$list}; |
|
17
|
|
|
|
|
51
|
|
131
|
|
|
|
|
|
|
} else { |
132
|
2
|
|
|
|
|
4
|
@list = ($list); |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
} else { |
135
|
21
|
|
|
|
|
46
|
@list = qw(Records); |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
40
|
|
|
|
|
115
|
@absolute{@list} = (0) x @list; |
139
|
40
|
|
|
|
|
189
|
$sort =~ s/$;.*//; |
140
|
|
|
|
|
|
|
#print STDERR "sort = $sort\n"; |
141
|
40
|
|
|
|
|
60
|
while (($key,$val) = each %{$self->{$group}}) { |
|
403
|
|
|
|
|
1362
|
|
142
|
363
|
|
|
|
|
973
|
$keys{$key} = $val->{$sort}; |
143
|
363
|
100
|
|
|
|
838
|
if ($key =~ /$;/) { |
144
|
155
|
|
|
|
|
379
|
my @key = split $;, $key; |
145
|
155
|
|
|
|
|
252
|
for (0 .. $#key) { |
146
|
375
|
100
|
|
|
|
727
|
$mklen[$_] = length($key[$_]) |
147
|
|
|
|
|
|
|
if length($key[$_]) > $mklen[$_]; |
148
|
|
|
|
|
|
|
} |
149
|
155
|
|
|
|
|
201
|
$mklen = $#mklen; |
150
|
155
|
|
|
|
|
316
|
grep ($mklen += $_, @mklen); |
151
|
|
|
|
|
|
|
} else { |
152
|
208
|
100
|
|
|
|
484
|
$mklen = length($key) if length($key) > $mklen; |
153
|
|
|
|
|
|
|
} |
154
|
363
|
|
|
|
|
479
|
for (@list) { |
155
|
435
|
50
|
|
|
|
1593
|
$absolute{$_} += $val->{$_} if defined $val->{$_}; |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
# chop keys to $Logfile::MAXWIDTH chars maximum; |
159
|
40
|
100
|
|
|
|
161
|
grep (($_=($_>$Logfile::MAXWIDTH)?$Logfile::MAXWIDTH:$_), @mklen); |
160
|
40
|
100
|
|
|
|
148
|
if ($group =~ /$;/) { |
161
|
5
|
|
|
|
|
23
|
my @key = split $;, $group; |
162
|
5
|
|
|
|
|
12
|
for (0 .. $#key) { |
163
|
12
|
|
|
|
|
65
|
printf "%-${mklen[$_]}s ", $key[$_]; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
} else { |
166
|
35
|
|
|
|
|
167
|
printf ("%-${mklen}s ", $group); |
167
|
|
|
|
|
|
|
} |
168
|
40
|
|
|
|
|
76
|
for (@list) { |
169
|
57
|
|
|
|
|
147
|
printf("%16s ", $_); |
170
|
|
|
|
|
|
|
} |
171
|
40
|
|
|
|
|
73
|
print "\n"; |
172
|
40
|
|
|
|
|
95
|
print '=' x ($mklen + (@list * 17)); |
173
|
40
|
|
|
|
|
103
|
print "\n"; |
174
|
|
|
|
|
|
|
#for $key (keys %keys) { |
175
|
|
|
|
|
|
|
# print STDERR "** $key $keys{$key}\n"; |
176
|
|
|
|
|
|
|
#} |
177
|
40
|
|
|
|
|
184
|
for $key (sort {&srt($rever, $keys{$a}, $keys{$b})} |
|
1024
|
|
|
|
|
1759
|
|
178
|
|
|
|
|
|
|
keys %keys) { |
179
|
301
|
|
|
|
|
571
|
my $val = $self->{$group}->{$key}; |
180
|
301
|
100
|
|
|
|
850
|
if ($key =~ /$;/) { |
181
|
155
|
|
|
|
|
421
|
my @key = split $;, $key; |
182
|
155
|
|
|
|
|
277
|
for (0 .. $#key) { |
183
|
375
|
|
|
|
|
1454
|
printf "%-${mklen[$_]}s ", substr($key[$_],0,$mklen[$_]); |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
} else { |
186
|
146
|
|
|
|
|
415
|
printf "%-${mklen}s ", $key; |
187
|
|
|
|
|
|
|
} |
188
|
301
|
|
|
|
|
471
|
for $list (@list) { |
189
|
365
|
50
|
|
|
|
842
|
my $ba = (defined $val->{$list})?$val->{$list}:0; |
190
|
365
|
50
|
|
|
|
640
|
if ($absolute{$list} > 0) { |
191
|
365
|
|
|
|
|
570
|
my $br = $ba/$absolute{$list}*100; |
192
|
365
|
|
|
|
|
6180
|
printf "%9d%6.2f%% ", $ba, $br; |
193
|
|
|
|
|
|
|
} else { |
194
|
0
|
|
|
|
|
0
|
printf "%15s ", $ba; |
195
|
|
|
|
|
|
|
} |
196
|
|
|
|
|
|
|
} |
197
|
301
|
|
|
|
|
427
|
print "\n"; |
198
|
301
|
100
|
100
|
|
|
986
|
last if defined $par{Top} && --$par{Top} <= 0; |
199
|
|
|
|
|
|
|
} |
200
|
40
|
|
|
|
|
281
|
print "\f"; |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub srt { |
204
|
1024
|
|
|
1024
|
0
|
1154
|
my $rev = shift; |
205
|
1024
|
|
|
|
|
976
|
my ($y,$x); |
206
|
1024
|
100
|
|
|
|
1590
|
if ($rev) { |
207
|
290
|
|
|
|
|
489
|
($x,$y) = @_; |
208
|
|
|
|
|
|
|
} else { |
209
|
734
|
|
|
|
|
1687
|
($y,$x) = @_; |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
1024
|
100
|
66
|
|
|
4921
|
if ($x =~ /[^\d.]|^$/o or $y =~ /[^\d.]|^$/o) { |
213
|
383
|
|
|
|
|
716
|
lc $y cmp lc $x; |
214
|
|
|
|
|
|
|
} else { |
215
|
641
|
|
|
|
|
2026
|
$x <=> $y; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
sub keys { |
220
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
221
|
0
|
|
|
|
|
0
|
my $group = shift; |
222
|
|
|
|
|
|
|
|
223
|
0
|
|
|
|
|
0
|
keys %{$self->{$group}}; |
|
0
|
|
|
|
|
0
|
|
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub all { |
227
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
228
|
0
|
|
|
|
|
0
|
my $group = shift; |
229
|
|
|
|
|
|
|
|
230
|
0
|
|
|
|
|
0
|
%{$self->{$group}}; |
|
0
|
|
|
|
|
0
|
|
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
package Logfile::Base::Record; |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
BEGIN { |
236
|
8
|
|
|
8
|
|
28
|
eval {require GetDate;}; |
|
8
|
|
|
|
|
3320
|
|
237
|
8
|
50
|
|
|
|
56
|
$HaveGetDate = ($@ eq "") and import GetDate 'getdate'; |
238
|
8
|
50
|
|
|
|
37
|
unless ($HaveGetDate) { |
239
|
8
|
|
|
|
|
13
|
eval {require Date::GetDate}; |
|
8
|
|
|
|
|
2683
|
|
240
|
8
|
50
|
|
|
|
58
|
$HaveDateGetDate = ($@ eq "") and import GetDate 'getdate'; |
241
|
8
|
50
|
|
|
|
26
|
unless ($HaveDateGetDate) { |
242
|
8
|
|
|
|
|
11
|
eval { |
243
|
8
|
|
|
|
|
3026
|
require Time::ParseDate; |
244
|
0
|
|
|
0
|
|
0
|
sub parsedate { &Time::ParseDate::parsedate(@_) } |
245
|
|
|
|
|
|
|
}; |
246
|
8
|
|
|
|
|
645
|
$HaveParseDate = ($@ eq ""); |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
}; |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
unless ($HaveGetDate or $HaveDateGetDate |
252
|
|
|
|
|
|
|
or $HaveParseDate) { |
253
|
8
|
50
|
|
8
|
|
7867
|
eval join '', ; |
|
8
|
50
|
|
402
|
|
15688
|
|
|
8
|
100
|
|
|
|
7558
|
|
|
402
|
100
|
|
|
|
670
|
|
|
402
|
50
|
|
|
|
755
|
|
|
402
|
100
|
|
|
|
3932
|
|
|
0
|
100
|
|
|
|
0
|
|
|
0
|
100
|
|
|
|
0
|
|
|
360
|
|
|
|
|
1231
|
|
|
19
|
|
|
|
|
59
|
|
|
23
|
|
|
|
|
54
|
|
|
23
|
|
|
|
|
39
|
|
|
23
|
|
|
|
|
109
|
|
|
23
|
|
|
|
|
42
|
|
|
402
|
|
|
|
|
2177
|
|
|
383
|
|
|
|
|
939
|
|
|
402
|
|
|
|
|
1045
|
|
|
402
|
|
|
|
|
1004
|
|
|
402
|
|
|
|
|
18679
|
|
|
360
|
|
|
|
|
981
|
|
|
402
|
|
|
|
|
1068
|
|
254
|
|
|
|
|
|
|
croak("Could not load my own date parsing: $@") |
255
|
|
|
|
|
|
|
if length($@); |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
8
|
|
|
8
|
|
5585
|
use Net::Country; |
|
8
|
|
|
|
|
20
|
|
|
8
|
|
|
|
|
5531
|
|
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
sub new { |
261
|
402
|
|
|
402
|
|
518
|
my $type = shift; |
262
|
402
|
|
|
|
|
1685
|
my %par = @_; |
263
|
402
|
|
|
|
|
581
|
my $self = {}; |
264
|
402
|
|
|
|
|
457
|
my ($sec,$min,$hours,$mday,$mon,$year, $time); |
265
|
|
|
|
|
|
|
|
266
|
402
|
|
|
|
|
812
|
%{$self} = %par; |
|
402
|
|
|
|
|
1424
|
|
267
|
|
|
|
|
|
|
|
268
|
402
|
50
|
|
|
|
1076
|
if ($par{Date}) { |
269
|
|
|
|
|
|
|
#print "$par{Date} => "; |
270
|
402
|
50
|
|
|
|
1029
|
if ($HaveGetDate) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
271
|
0
|
|
|
|
|
0
|
$par{Date} =~ s!(\d\d\d\d):!$1 !o; |
272
|
0
|
|
|
|
|
0
|
$par{Date} =~ s!/! !go; |
273
|
0
|
|
|
|
|
0
|
$time = getdate($par{Date}); |
274
|
|
|
|
|
|
|
} elsif ($HaveDateGetDate) { |
275
|
0
|
|
|
|
|
0
|
$par{Date} =~ s!(\d\d\d\d):!$1 !o; |
276
|
0
|
|
|
|
|
0
|
$par{Date} =~ s!/! !go; |
277
|
0
|
|
|
|
|
0
|
$time = Date::GetDate::getdate($par{Date}); |
278
|
|
|
|
|
|
|
} elsif ($HaveParseDate) { |
279
|
|
|
|
|
|
|
|
280
|
0
|
|
|
|
|
0
|
$time = parsedate($par{Date}, |
281
|
|
|
|
|
|
|
FUZZY => 1, |
282
|
|
|
|
|
|
|
NO_RELATIVE => 1); |
283
|
|
|
|
|
|
|
} else { |
284
|
402
|
|
|
|
|
10631
|
$time = &Time::String::to_time($par{Date}); |
285
|
|
|
|
|
|
|
} |
286
|
402
|
|
|
|
|
8953
|
($sec,$min,$hours,$mday,$mon,$year) = localtime($time); |
287
|
|
|
|
|
|
|
#print "$par{Date} => (s>$sec,m>$min,h>$hours,m>$mday,m>$mon,y>$year)\n"; |
288
|
402
|
|
100
|
|
|
2786
|
$self->{Hour} = sprintf "%02d", $self->{Hour}||$hours; |
289
|
402
|
|
|
|
|
1371
|
$self->{Date} = sprintf("%02d%02d%02d", $year%100, $mon+1, $mday); |
290
|
|
|
|
|
|
|
} |
291
|
402
|
100
|
|
|
|
897
|
if ($par{Host}) { |
292
|
380
|
|
|
|
|
878
|
my $host = $self->{Host} = lc($par{Host}); |
293
|
380
|
100
|
|
|
|
1164
|
if ($host =~ /[^\d.]/) { |
294
|
335
|
100
|
|
|
|
794
|
if ($host =~ /\./) { |
295
|
206
|
|
|
|
|
1010
|
$self->{Domain} = Net::Country::Name((split /\./, $host)[-1]); |
296
|
|
|
|
|
|
|
} else { |
297
|
129
|
|
|
|
|
263
|
$self->{Domain} = 'Local'; |
298
|
|
|
|
|
|
|
} |
299
|
|
|
|
|
|
|
} else { |
300
|
45
|
|
|
|
|
90
|
$self->{Domain} = 'Unresolved'; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
} |
303
|
402
|
|
|
|
|
882
|
$self->{Records} = 1; |
304
|
|
|
|
|
|
|
|
305
|
402
|
|
|
|
|
2224
|
bless $self, $type; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub add { |
309
|
1089
|
|
|
1089
|
|
1237
|
my $self = shift; |
310
|
1089
|
|
|
|
|
1081
|
my $other = shift; |
311
|
1089
|
|
|
|
|
1093
|
my $ignore = shift; |
312
|
|
|
|
|
|
|
|
313
|
1089
|
|
|
|
|
1050
|
for (keys %{$other}) { |
|
1089
|
|
|
|
|
3433
|
|
314
|
8797
|
100
|
|
|
|
15798
|
next if $_ eq $ignore; |
315
|
8021
|
100
|
|
|
|
18368
|
next unless defined $other->{$_}; |
316
|
7994
|
100
|
|
|
|
14441
|
next unless length($other->{$_}); |
317
|
7607
|
100
|
|
|
|
19169
|
next if $other->{$_} =~ /\D/; |
318
|
3813
|
|
|
|
|
6837
|
$self->{$_} += $other->{$_}; |
319
|
|
|
|
|
|
|
} |
320
|
|
|
|
|
|
|
|
321
|
1089
|
|
|
|
|
4770
|
$self; |
322
|
|
|
|
|
|
|
} |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
sub copy { |
325
|
386
|
|
|
386
|
|
463
|
my $self = shift; |
326
|
386
|
|
|
|
|
382
|
my %new = %{$self}; |
|
386
|
|
|
|
|
2882
|
|
327
|
|
|
|
|
|
|
|
328
|
386
|
|
|
|
|
2918
|
bless \%new, ref($self); |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
0
|
|
|
0
|
|
|
sub requests {$_[0]->{Records};} |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
1; |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
__DATA__ |