source: trunk/third/xntp/scripts/summary.pl @ 10832

Revision 10832, 10.6 KB checked in by brlewis, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10831, which included commits to RCS files with non-trunk default branches.
Line 
1#!/usr/bin/perl -w
2# $Id: summary.pl,v 1.1.1.1 1997-12-02 20:29:04 brlewis Exp $
3# Perl version of (summary.sh, loop.awk, peer.awk):
4# Create summaries from xntpd's loop and peer statistics.
5#
6# Copyright (c) 1997, Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful, but
14# WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16# General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22require 5.003; # "never tested with any other version of Perl"
23use strict;
24
25use Getopt::Long;
26
27my $statsdir = "/tmp/xntpd";
28my $skip_time_steps = 3600.0;           # ignore time offsets larger that this
29my $startdate = "19700101";             # first data file to use
30my $enddate=`date -u +%Y%m%d`; chomp $enddate; --$enddate;
31my $peer_dist_limit = 400.0;
32
33my %options = ("directory=s" => \$statsdir,
34               "skip-time-steps:f" => \$skip_time_steps,
35               "start-date=s" => \$startdate,
36               "end-date=s" => \$enddate,
37               "peer-dist-limit=f" => \$peer_dist_limit);
38
39if ( !GetOptions(%options) )
40{
41    print STDERR "valid options for $0 are:\n";
42    my $opt;
43    foreach $opt (sort(keys %options)) {
44        print STDERR "\t--$opt ";
45        if ( ref($options{$opt}) eq "ARRAY" ) {
46            print STDERR "(" . join (" ", @{$options{$opt}}) . ")\n";
47        } else {
48            print STDERR "(${$options{$opt}})\n";
49        }
50    }
51    print STDERR "\n";
52    die;
53}
54
55die "$statsdir: no such directory" unless (-d $statsdir);
56die "$skip_time_steps: skip-time-steps must be positive"
57    unless ($skip_time_steps >= 0.0);
58die "$startdate: invalid start date"
59    unless ($startdate =~ m/.*([12]\d{3}[01]\d[0-3]\d)$/);
60die "$enddate: invalid end date"
61    unless ($enddate =~ m/.*([12]\d{3}[01]\d[0-3]\d)$/);
62
63$skip_time_steps = 0.128 if ($skip_time_steps == 0);
64
65sub min
66{
67    my ($result, @rest) = @_;
68    map { $result = $_ if ($_ < $result) } @rest;
69    return($result);
70}
71
72sub max
73{
74    my ($result, @rest) = @_;
75    map { $result = $_ if ($_ > $result) } @rest;
76    return($result);
77}
78
79# calculate mean, range, and standard deviation for offset and frequency
80sub do_loop
81{
82    my ($directory, $fname, $out_file) = @_;
83    print "$directory/$fname\n";
84    open INPUT, "$directory/$fname";
85    open OUTPUT, ">>$out_file" or die "can't open $out_file: $!";
86    print OUTPUT "$fname\n";
87    my ($loop_tmax, $loop_fmax) = (-1e9, -1e9);
88    my ($loop_tmin, $loop_fmin) = (1e9, 1e9);
89    my ($loop_time_rms, $loop_freq_rms) = (0, 0);
90    my $loop_count = 0;
91    my $loop_time = 0;
92    my $loop_freq = 0;
93    my ($freq, $offs);
94    my @Fld;
95    while (<INPUT>) {
96        chop;   # strip record separator
97        @Fld = split;
98        next if ($#Fld != 4);
99# 50529 74356.259 -0.000112 16.1230 8
100        if ($Fld[2] > $skip_time_steps || $Fld[2] < -$skip_time_steps) {
101            warn "ignoring loop offset $Fld[2] (file $fname, line $.)\n";
102            next
103        }
104        $loop_count++;
105        ($offs, $freq) = ($Fld[2], $Fld[3]);
106        $loop_tmax = max($loop_tmax, $offs);
107        $loop_tmin = min($loop_tmin, $offs);
108        $loop_fmax = max($loop_fmax, $freq);
109        $loop_fmin = min($loop_fmin, $freq);
110        $loop_time += $offs;
111        $loop_time_rms += $offs * $offs;
112        $loop_freq += $freq;
113        $loop_freq_rms += $freq * $freq;
114    }
115    close INPUT;
116    if ($loop_count > 1) {
117        $loop_time /= $loop_count;
118        $loop_time_rms = $loop_time_rms / $loop_count - $loop_time * $loop_time;
119        if ($loop_time_rms < 0) {
120            warn "loop_time_rms: $loop_time_rms < 0";
121            $loop_time_rms = 0;
122        }
123        $loop_time_rms = sqrt($loop_time_rms);
124        $loop_freq /= $loop_count;
125        $loop_freq_rms = $loop_freq_rms / $loop_count - $loop_freq * $loop_freq;
126        if ($loop_freq_rms < 0) {
127            warn "loop_freq_rms: $loop_freq_rms < 0";
128            $loop_freq_rms = 0;
129        }
130        $loop_freq_rms = sqrt($loop_freq_rms);
131        printf OUTPUT
132            ("loop %d, %.0f+/-%.1f, rms %.1f, freq %.2f+/-%0.3f, var %.3f\n",
133             $loop_count, ($loop_tmax + $loop_tmin) / 2 * 1e6,
134             ($loop_tmax - $loop_tmin) / 2 * 1e6, $loop_time_rms * 1e6,
135             ($loop_fmax + $loop_fmin) / 2, ($loop_fmax - $loop_fmin) / 2,
136             $loop_freq_rms);
137    }
138    else {
139        warn "no valid lines in $directory/$fname";
140    }
141    close OUTPUT
142}
143
144# calculate mean, standard deviation, maximum offset, mean dispersion,
145# and maximum distance for each peer
146sub do_peer
147{
148    my ($directory, $fname, $out_file) = @_;
149    print "$directory/$fname\n";
150    open INPUT, "$directory/$fname";
151    open OUTPUT, ">>$out_file" or die "can't open $out_file: $!";
152    print OUTPUT "$fname\n";
153# we toss out all distances greater than one second on the assumption the
154# peer is in initial acquisition
155    my ($n, $MAXDISTANCE) = (0, 1.0);
156    my %peer_time;
157    my %peer_time_rms;
158    my %peer_count;
159    my %peer_delay;
160    my %peer_disp;
161    my %peer_dist;
162    my %peer_ident;
163    my %peer_tmin;
164    my %peer_tmax;
165    my @Fld;
166    my ($i, $j);
167    my ($dist, $offs);
168    while (<INPUT>) {
169        chop;   # strip record separator
170        @Fld = split;
171        next if ($#Fld != 6);
172# 50529 83316.249 127.127.8.1 9674 0.008628 0.00000 0.00700
173        $dist = $Fld[6] + $Fld[5] / 2;
174        next if ($dist > $MAXDISTANCE);
175        $offs = $Fld[4];
176        if ($offs > $skip_time_steps || $offs < -$skip_time_steps) {
177            warn "ignoring peer offset $offs (file $fname, line $.)\n";
178            next
179        }
180        $i = $n;
181        for ($j = 0; $j < $n; $j++) {
182            if ($Fld[2] eq $peer_ident{$j}) {
183                $i = $j;                # peer found
184                last;
185            }
186        }
187        if ($i == $n) {         # add new peer
188            $peer_ident{$i} = $Fld[2];
189            $peer_tmax{$i} = $peer_dist{$i} = -1e9;
190            $peer_tmin{$i} = 1e9;
191            $peer_time{$i} = $peer_time_rms{$i} = 0;
192            $peer_delay{$i} = $peer_disp{$i} = 0;
193            $peer_count{$i} = 0;
194            $n++;
195        }
196        $peer_count{$i}++;
197        $peer_tmax{$i} = max($peer_tmax{$i}, $offs);
198        $peer_tmin{$i} = min($peer_tmin{$i}, $offs);
199        $peer_dist{$i} = max($peer_dist{$i}, $dist);
200        $peer_time{$i} += $offs;
201        $peer_time_rms{$i} += $offs * $offs;
202        $peer_delay{$i} += $Fld[5];
203        $peer_disp{$i} += $Fld[6];
204    }
205    close INPUT;
206    print OUTPUT
207"       ident     cnt     mean     rms      max     delay     dist     disp\n";
208    print OUTPUT
209"==========================================================================\n";
210    my @lines = ();
211    for ($i = 0; $i < $n; $i++) {
212        next if $peer_count{$i} < 2;
213        $peer_time{$i} /= $peer_count{$i};
214        $peer_time_rms{$i} = sqrt($peer_time_rms{$i} / $peer_count{$i} -
215                                  $peer_time{$i} * $peer_time{$i});
216        $peer_delay{$i} /= $peer_count{$i};
217        $peer_disp{$i} /= $peer_count{$i};
218        $peer_tmax{$i} = $peer_tmax{$i} - $peer_time{$i};
219        $peer_tmin{$i} = $peer_time{$i} - $peer_tmin{$i};
220        if ($peer_tmin{$i} > $peer_tmax{$i}) {  # can this happen at all?
221            $peer_tmax{$i} = $peer_tmin{$i};
222        }
223        push @lines, sprintf
224            "%-15s %4d %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n",
225            $peer_ident{$i}, $peer_count{$i}, $peer_time{$i} * 1e3,
226            $peer_time_rms{$i} * 1e3, $peer_tmax{$i} * 1e3,
227            $peer_delay{$i} * 1e3, $peer_dist{$i} * 1e3, $peer_disp{$i} * 1e3;
228    }
229    print OUTPUT sort @lines;
230    close OUTPUT;
231}
232
233sub do_clock
234{
235    my ($directory, $fname, $out_file) = @_;
236    print "$directory/$fname\n";
237    open INPUT, "$directory/$fname";
238    open OUTPUT, ">>$out_file" or die "can't open $out_file: $!";
239    print OUTPUT "$fname\n";
240    close INPUT;
241    close OUTPUT;
242}
243
244sub peer_summary
245{
246    my $in_file = shift;
247    my ($i, $j, $n);
248    my (%peer_ident, %peer_count, %peer_mean, %peer_var, %peer_max);
249    my (%peer_1, %peer_2, %peer_3, %peer_4);
250    my $dist;
251    my $max;
252    open INPUT, "<$in_file" or die "can't open $in_file: $!";
253    my @Fld;
254    $n = 0;
255    while (<INPUT>) {
256        chop;   # strip record separator
257        @Fld = split;
258        next if ($#Fld < 7 || $Fld[0] eq 'ident');
259        $i = $n;
260        for ($j = 0; $j < $n; $j++) {
261            if ($Fld[0] eq $peer_ident{$j}) {
262                $i = $j;
263                last;                   # peer found
264            }
265        }
266        if ($i == $n) {                 # add new peer
267            $peer_count{$i} = $peer_mean{$i} = $peer_var{$i} = 0;
268            $peer_max{$i} = 0;
269            $peer_1{$i} = $peer_2{$i} = $peer_3{$i} = $peer_4{$i} = 0;
270            $peer_ident{$i} = $Fld[0];
271            ++$n;
272        }
273        $dist = $Fld[6] - $Fld[5] / 2;
274        if ($dist < $peer_dist_limit) {
275            $peer_count{$i}++;
276            $peer_mean{$i} += $Fld[2];
277            $peer_var{$i} += $Fld[3] * $Fld[3];
278            $max = $Fld[4];
279            $peer_max{$i} = max($peer_max{$i}, $max);
280            if ($max > 1) {
281                $peer_1{$i}++;
282                if ($max > 5) {
283                    $peer_2{$i}++;
284                    if ($max > 10) {
285                        $peer_3{$i}++;
286                        if ($max > 50) {
287                            $peer_4{$i}++;
288                        }
289                    }
290                }
291            }
292        }
293        else {
294            warn "dist exceeds limit: $dist (file $in_file, line $.)\n";
295        }
296    }
297    close INPUT;
298    my @lines = ();
299    print
300        "       host     days    mean       rms       max   >1  >5 >10 >50\n";
301    print
302        "==================================================================\n";
303    for ($i = 0; $i < $n; $i++) {
304        next if ($peer_count{$i} < 2);
305        $peer_mean{$i} /= $peer_count{$i};
306        $peer_var{$i} = sqrt($peer_var{$i} / $peer_count{$i} -
307                             $peer_mean{$i} * $peer_mean{$i});
308        push @lines, sprintf
309            "%-15s %3d %9.3f% 9.3f %9.3f %3d %3d %3d %3d\n",
310            $peer_ident{$i}, $peer_count{$i}, $peer_mean{$i}, $peer_var{$i},
311            $peer_max{$i}, $peer_1{$i}, $peer_2{$i}, $peer_3{$i}, $peer_4{$i};
312    }
313    print sort @lines;
314}
315
316my $loop_summary="/tmp/loop_summary";
317my $peer_summary="/tmp/peer_summary";
318my $clock_summary="/tmp/clock_summary";
319my (@loopfiles, @peerfiles, @clockfiles);
320
321print STDERR "Creating summaries from $statsdir ($startdate to $enddate)\n";
322
323opendir SDIR, $statsdir or die "directory ${statsdir}: $!";
324rewinddir SDIR;
325@loopfiles=sort grep /loop.*[12]\d{3}[01]\d[0-3]\d/, readdir SDIR;
326rewinddir SDIR;
327@peerfiles=sort grep /peer.*[12]\d{3}[01]\d[0-3]\d/, readdir SDIR;
328rewinddir SDIR;
329@clockfiles=sort grep /clock.*[12]\d{3}[01]\d[0-3]\d/, readdir SDIR;
330closedir SDIR;
331
332map { unlink $_ if -f $_ } ($loop_summary, $peer_summary, $clock_summary);
333
334my $date;
335map {
336    $date = $_; $date =~ s/.*([12]\d{3}[01]\d[0-3]\d)$/$1/;
337    if ($date ge $startdate && $date le $enddate) {
338        do_loop $statsdir, $_, $loop_summary;
339    }
340} @loopfiles;
341
342map {
343    $date = $_; $date =~ s/.*([12]\d{3}[01]\d[0-3]\d)$/$1/;
344    if ($date ge $startdate && $date le $enddate) {
345        do_peer $statsdir, $_, $peer_summary;
346    }
347} @peerfiles;
348
349map {
350    $date = $_; $date =~ s/.*([12]\d{3}[01]\d[0-3]\d)$/$1/;
351    if ($date ge $startdate && $date le $enddate) {
352        do_clock $statsdir, $_, $clock_summary;
353    }
354} @clockfiles;
355
356print STDERR "Creating peer summary with limit $peer_dist_limit\n";
357peer_summary $peer_summary if (-f $peer_summary);
Note: See TracBrowser for help on using the repository browser.