1c0b746e5SOllivier Robert#!/usr/bin/perl -w 2c0b746e5SOllivier Robert;# --*-perl-*-- 3c0b746e5SOllivier Robert;# 4ea906c41SOllivier Robert;# /src/NTP/ntp4-dev/scripts/monitoring/ntploopwatch,v 4.7 2004/11/14 16:11:05 kardel RELEASE_20050508_A 5c0b746e5SOllivier Robert;# 6c0b746e5SOllivier Robert;# process loop filter statistics file and either 7c0b746e5SOllivier Robert;# - show statistics periodically using gnuplot 8c0b746e5SOllivier Robert;# - or print a single plot 9c0b746e5SOllivier Robert;# 10c0b746e5SOllivier Robert;# Copyright (c) 1992-1998 11c0b746e5SOllivier Robert;# Rainer Pruy, Friedrich-Alexander Universit�t Erlangen-N�rnberg 12c0b746e5SOllivier Robert;# 13c0b746e5SOllivier Robert;# 14c0b746e5SOllivier Robert;############################################################# 15c0b746e5SOllivier Robert$0 =~ s!^.*/([^/]+)$!$1!; 16c0b746e5SOllivier Robert$F = ' ' x length($0); 17c0b746e5SOllivier Robert$|=1; 18c0b746e5SOllivier Robert 19c0b746e5SOllivier Robert$ENV{'SHELL'} = '/bin/sh'; # use bourne shell 20c0b746e5SOllivier Robert 21c0b746e5SOllivier Robertundef($config); 22c0b746e5SOllivier Robertundef($workdir); 23c0b746e5SOllivier Robertundef($PrintIt); 24c0b746e5SOllivier Robertundef($samples); 25c0b746e5SOllivier Robertundef($StartTime); 26c0b746e5SOllivier Robertundef($EndTime); 27c0b746e5SOllivier Robert($a,$b) if 0; # keep -w happy 28c0b746e5SOllivier Robert$usage = <<"E-O-P"; 29c0b746e5SOllivier Robertusage: 30c0b746e5SOllivier Robert to watch statistics permanently: 31c0b746e5SOllivier Robert $0 [-v[<level>]] [-c <config-file>] [-d <working-dir>] 32c0b746e5SOllivier Robert $F [-h <hostname>] 33c0b746e5SOllivier Robert 34c0b746e5SOllivier Robert to get a single print out specify also 35c0b746e5SOllivier Robert $F -P[<printer>] [-s<samples>] 36c0b746e5SOllivier Robert $F [-S <start-time>] [-E <end-time>] 37c0b746e5SOllivier Robert $F [-Y <MaxOffs>] [-y <MinOffs>] 38c0b746e5SOllivier Robert 39c0b746e5SOllivier RobertIf You like long option names, You can use: 40c0b746e5SOllivier Robert -help 41c0b746e5SOllivier Robert -c +config 42c0b746e5SOllivier Robert -d +directory 43c0b746e5SOllivier Robert -h +host 44c0b746e5SOllivier Robert -v +verbose[=<level>] 45c0b746e5SOllivier Robert -P +printer[=<printer>] 46c0b746e5SOllivier Robert -s +samples[=<samples>] 47c0b746e5SOllivier Robert -S +starttime 48c0b746e5SOllivier Robert -E +endtime 49c0b746e5SOllivier Robert -Y +maxy 50c0b746e5SOllivier Robert -y +miny 51c0b746e5SOllivier Robert 52c0b746e5SOllivier RobertIf <printer> contains a '/' (slash character) output is directed to 53c0b746e5SOllivier Roberta file of this name instead of delivered to a printer. 54c0b746e5SOllivier RobertE-O-P 55c0b746e5SOllivier Robert 56c0b746e5SOllivier Robert;# add directory to look for lr.pl and timelocal.pl (in front of current list) 57ea906c41SOllivier Robertunshift(@INC,"."); 58c0b746e5SOllivier Robert 59c0b746e5SOllivier Robertrequire "lr.pl"; # linear regresion routines 60c0b746e5SOllivier Robert 61c0b746e5SOllivier Robert$MJD_1970 = 40587; # from ntp.h (V3) 62c0b746e5SOllivier Robert$RecordSize = 48; # usually a line fits into 42 bytes 63c0b746e5SOllivier Robert$MinClip = 1; # clip Y scales with greater range than this 64c0b746e5SOllivier Robert 65c0b746e5SOllivier Robert;# largest extension of Y scale from mean value, factor for standart deviation 66c0b746e5SOllivier Robert$FuzzLow = 2.2; # for side closer to zero 67c0b746e5SOllivier Robert$FuzzBig = 1.8; # for side farther from zero 68c0b746e5SOllivier Robert 69c0b746e5SOllivier Robertrequire "ctime.pl"; 70c0b746e5SOllivier Robertrequire "timelocal.pl"; 71c0b746e5SOllivier Robert;# early distributions of ctime.pl had a bug 72c0b746e5SOllivier Robert$ENV{'TZ'} = 'MET' unless defined $ENV{'TZ'} || $[ > 4.010; 73c0b746e5SOllivier Robertif (defined(@ctime'MoY)) 74c0b746e5SOllivier Robert{ 75c0b746e5SOllivier Robert *Month=*ctime'MoY; 76c0b746e5SOllivier Robert *Day=*ctime'DoW; 77c0b746e5SOllivier Robert} # ' re-sync emacs fontification 78c0b746e5SOllivier Robertelse 79c0b746e5SOllivier Robert{ 80c0b746e5SOllivier Robert @Month = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); 81c0b746e5SOllivier Robert @Day = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); 82c0b746e5SOllivier Robert} 83c0b746e5SOllivier Robertprint @ctime'DoW if 0; # ' re-sync emacs fontification 84c0b746e5SOllivier Robert 85c0b746e5SOllivier Robert;# max number of days per month 86c0b746e5SOllivier Robert@MaxNumDaysPerMonth = (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); 87c0b746e5SOllivier Robert 88c0b746e5SOllivier Robert;# config settable parameters 89c0b746e5SOllivier Robert$delay = 60; 90c0b746e5SOllivier Robert$srcprefix = "./var\@\$STATHOST/loopstats."; 91c0b746e5SOllivier Robert$showoffs = 1; 92c0b746e5SOllivier Robert$showfreq = 1; 93c0b746e5SOllivier Robert$showcmpl = 0; 94c0b746e5SOllivier Robert$showoreg = 0; 95c0b746e5SOllivier Robert$showfreg = 0; 96c0b746e5SOllivier Robertundef($timebase); 97c0b746e5SOllivier Robertundef($freqbase); 98c0b746e5SOllivier Robertundef($cmplscale); 99c0b746e5SOllivier Robertundef($MaxY); 100c0b746e5SOllivier Robertundef($MinY); 101c0b746e5SOllivier Robert$deltaT = 512; # indicate sample data gaps greater than $deltaT seconds 102c0b746e5SOllivier Robert$verbose = 1; 103c0b746e5SOllivier Robert 104c0b746e5SOllivier Robertwhile($_ = shift(@ARGV)) 105c0b746e5SOllivier Robert{ 106c0b746e5SOllivier Robert (/^[+-]help$/) && die($usage); 107c0b746e5SOllivier Robert 108c0b746e5SOllivier Robert (/^-c$/ || /^\+config$/) && 109c0b746e5SOllivier Robert (@ARGV || die($usage), $config = shift(@ARGV), next); 110c0b746e5SOllivier Robert 111c0b746e5SOllivier Robert (/^-d$/ || /^\+directory$/) && 112c0b746e5SOllivier Robert (@ARGV || die($usage), $workdir = shift(@ARGV), next); 113c0b746e5SOllivier Robert 114c0b746e5SOllivier Robert (/^-h$/ || /^\+host$/) && 115c0b746e5SOllivier Robert (@ARGV || die($usage), $STATHOST = shift, next); 116c0b746e5SOllivier Robert 117c0b746e5SOllivier Robert (/^-v(\d*)$/ || /^\+verbose=?(\d*)$/) && 118c0b746e5SOllivier Robert ($verbose=($1 eq "") ? 1 : $1, next); 119c0b746e5SOllivier Robert 120c0b746e5SOllivier Robert (/^-P(\S*)$/ || /^\+[Pp]rinter=?(\S*)$/) && 121c0b746e5SOllivier Robert ($PrintIt = $1, $verbose==1 && ($verbose = 0), next); 122c0b746e5SOllivier Robert 123c0b746e5SOllivier Robert (/^-s(\d*)$/ || /^\+samples=?(\d*)$/) && 124c0b746e5SOllivier Robert (($samples = ($1 eq "") ? (shift || die($usage)): $1), next); 125c0b746e5SOllivier Robert 126c0b746e5SOllivier Robert (/^-S$/ || /^\+[Ss]tart[Tt]ime$/) && 127c0b746e5SOllivier Robert (@ARGV || die($usage), $StartTime=&date_time_spec2seconds(shift),next); 128c0b746e5SOllivier Robert 129c0b746e5SOllivier Robert (/^-E$/ || /^\+[Ee]nd[Tt]ime$/) && 130c0b746e5SOllivier Robert (@ARGV || die($usage), $EndTime = &date_time_spec2seconds(shift),next); 131c0b746e5SOllivier Robert 132c0b746e5SOllivier Robert (/^-Y$/ || /^\+[Mm]ax[Yy]$/) && 133c0b746e5SOllivier Robert (@ARGV || die($usage), $MaxY = shift, next); 134c0b746e5SOllivier Robert 135c0b746e5SOllivier Robert (/^-y$/ || /^\+[Mm]in[Yy]$/) && 136c0b746e5SOllivier Robert (@ARGV || die($usage), $MinY = shift, next); 137c0b746e5SOllivier Robert 138c0b746e5SOllivier Robert die("$0: unexpected argument \"$_\"\n$usage"); 139c0b746e5SOllivier Robert} 140c0b746e5SOllivier Robert 141c0b746e5SOllivier Robertif (defined($workdir)) 142c0b746e5SOllivier Robert{ 143c0b746e5SOllivier Robert chdir($workdir) || 144c0b746e5SOllivier Robert die("$0: failed to change working dir to \"$workdir\": $!\n"); 145c0b746e5SOllivier Robert} 146c0b746e5SOllivier Robert 147c0b746e5SOllivier Robert$PrintIt = "ps" if defined($PrintIt) && $PrintIt eq ""; 148c0b746e5SOllivier Robert 149c0b746e5SOllivier Robertif (!defined($PrintIt)) 150c0b746e5SOllivier Robert{ 151c0b746e5SOllivier Robert defined($samples) && 152c0b746e5SOllivier Robert print "WARNING: your samples value may be shadowed by config file settings\n"; 153c0b746e5SOllivier Robert defined($StartTime) && 154c0b746e5SOllivier Robert print "WARNING: your StartTime value may be shadowed by config file settings\n"; 155c0b746e5SOllivier Robert defined($EndTime) && 156c0b746e5SOllivier Robert print "WARNING: your EndTime value may be shadowed by config file settings\n"; 157c0b746e5SOllivier Robert defined($MaxY) && 158c0b746e5SOllivier Robert print "WARNING: your MaxY value may be shadowed by config file settings\n"; 159c0b746e5SOllivier Robert defined($MinY) && 160c0b746e5SOllivier Robert print "WARNING: your MinY value may be shadowed by config file settings\n"; 161c0b746e5SOllivier Robert 162c0b746e5SOllivier Robert ;# check operating environment 163c0b746e5SOllivier Robert ;# 164c0b746e5SOllivier Robert ;# gnuplot usually has X support 165c0b746e5SOllivier Robert ;# I vaguely remember there was one with sunview support 166c0b746e5SOllivier Robert ;# 167c0b746e5SOllivier Robert ;# If Your plotcmd can display graphics using some other method 168c0b746e5SOllivier Robert ;# (Tek window,..) fix the following test 169c0b746e5SOllivier Robert ;# (or may be, just disable it) 170c0b746e5SOllivier Robert ;# 171c0b746e5SOllivier Robert !(defined($ENV{'DISPLAY'}) || defined($ENV{'WINDOW_PARENT'})) && 172c0b746e5SOllivier Robert die("Need window system to monitor statistics\n"); 173c0b746e5SOllivier Robert} 174c0b746e5SOllivier Robert 175c0b746e5SOllivier Robert;# configuration file 176c0b746e5SOllivier Robert$config = "loopwatch.config" unless defined($config); 177c0b746e5SOllivier Robert($STATHOST = $config) =~ s!.*loopwatch\.config.([^/\.]*)$!$1! 178c0b746e5SOllivier Robert unless defined($STATHOST); 179c0b746e5SOllivier Robert($STATTAG = $STATHOST) =~ s/^([^\.\*\s]+)\..*$/$1/; 180c0b746e5SOllivier Robert 181c0b746e5SOllivier Robert$srcprefix =~ s/\$STATHOST/$STATHOST/g; 182c0b746e5SOllivier Robert 183c0b746e5SOllivier Robert;# plot command 184c0b746e5SOllivier Robert@plotcmd=("gnuplot", 185c0b746e5SOllivier Robert '-title', "Ntp loop filter statistics $STATHOST", 186c0b746e5SOllivier Robert '-name', "NtpLoopWatch_$STATTAG"); 187c0b746e5SOllivier Robert$tmpfile = "/tmp/ntpstat.$$"; 188c0b746e5SOllivier Robert 189c0b746e5SOllivier Robert;# other variables 190c0b746e5SOllivier Robert$doplot = ""; # assembled command for @plotcmd to display plot 191c0b746e5SOllivier Robertundef($laststat); 192c0b746e5SOllivier Robert 193c0b746e5SOllivier Robert;# plot value ranges 194c0b746e5SOllivier Robertundef($mintime); 195c0b746e5SOllivier Robertundef($maxtime); 196c0b746e5SOllivier Robertundef($minoffs); 197c0b746e5SOllivier Robertundef($maxoffs); 198c0b746e5SOllivier Robertundef($minfreq); 199c0b746e5SOllivier Robertundef($maxfreq); 200c0b746e5SOllivier Robertundef($mincmpl); 201c0b746e5SOllivier Robertundef($maxcmpl); 202c0b746e5SOllivier Robertundef($miny); 203c0b746e5SOllivier Robertundef($maxy); 204c0b746e5SOllivier Robert 205c0b746e5SOllivier Robert;# stop operation if plot command dies 206c0b746e5SOllivier Robertsub sigchld 207c0b746e5SOllivier Robert{ 208c0b746e5SOllivier Robert local($pid) = wait; 209c0b746e5SOllivier Robert unlink($tmpfile); 210c0b746e5SOllivier Robert warn(sprintf("%s: %s died: exit status: %d signal %d\n", 211c0b746e5SOllivier Robert $0, 212c0b746e5SOllivier Robert (defined($Plotpid) && $Plotpid == $pid) 213c0b746e5SOllivier Robert ? "plotcmd" : "unknown child $pid", 214c0b746e5SOllivier Robert $?>>8,$? & 0xff)) if $?; 215c0b746e5SOllivier Robert exit(1) if $? && defined($Plotpid) && $pid == $Plotpid; 216c0b746e5SOllivier Robert} 217c0b746e5SOllivier Robert&sigchld if 0; 218c0b746e5SOllivier Robert$SIG{'CHLD'} = "sigchld"; 219c0b746e5SOllivier Robert$SIG{'CLD'} = "sigchld"; 220c0b746e5SOllivier Robert 221c0b746e5SOllivier Robertsub abort 222c0b746e5SOllivier Robert{ 223c0b746e5SOllivier Robert unlink($tmpfile); 224c0b746e5SOllivier Robert defined($Plotpid) && kill('TERM',$Plotpid); 225c0b746e5SOllivier Robert die("$0: received signal SIG$_[$[] - exiting\n"); 226c0b746e5SOllivier Robert} 227c0b746e5SOllivier Robert&abort if 0; # make -w happy - &abort IS used 228c0b746e5SOllivier Robert$SIG{'INT'} = $SIG{'HUP'} = $SIG{'QUIT'} = $SIG{'TERM'} = $SIG{'PIPE'} = "abort"; 229c0b746e5SOllivier Robert 230c0b746e5SOllivier Robert;# 231c0b746e5SOllivier Robertsub abs 232c0b746e5SOllivier Robert{ 233c0b746e5SOllivier Robert ($_[$[] < 0) ? -($_[$[]) : $_[$[]; 234c0b746e5SOllivier Robert} 235c0b746e5SOllivier Robert 236c0b746e5SOllivier Robertsub boolval 237c0b746e5SOllivier Robert{ 238c0b746e5SOllivier Robert local($v) = ($_[$[]); 239c0b746e5SOllivier Robert 240c0b746e5SOllivier Robert return 1 if ($v eq 'yes') || ($v eq 'y'); 241c0b746e5SOllivier Robert return 1 if ($v =~ /^[0-9]*$/) && ($v != 0); 242c0b746e5SOllivier Robert return 0; 243c0b746e5SOllivier Robert} 244c0b746e5SOllivier Robert 245c0b746e5SOllivier Robert;##################### 246c0b746e5SOllivier Robert;# start of real work 247c0b746e5SOllivier Robert 248c0b746e5SOllivier Robertprint "starting plot command (" . join(" ",@plotcmd) . ")\n" if $verbose > 1; 249c0b746e5SOllivier Robert 250c0b746e5SOllivier Robert$Plotpid = open(PLOT,"|-"); 251c0b746e5SOllivier Robertselect((select(PLOT),$|=1)[$[]); # make PLOT line bufferd 252c0b746e5SOllivier Robert 253c0b746e5SOllivier Robertdefined($Plotpid) || 254c0b746e5SOllivier Robert die("$0: failed to start plot command: $!\n"); 255c0b746e5SOllivier Robert 256c0b746e5SOllivier Robertunless ($Plotpid) 257c0b746e5SOllivier Robert{ 258c0b746e5SOllivier Robert ;# child == plot command 259c0b746e5SOllivier Robert close(STDOUT); 260c0b746e5SOllivier Robert open(STDOUT,">&STDERR") || 261c0b746e5SOllivier Robert die("$0: failed to redirect STDOUT of plot command: $!\n"); 262c0b746e5SOllivier Robert 263c0b746e5SOllivier Robert print STDOUT "plot command running as $$\n"; 264c0b746e5SOllivier Robert 265c0b746e5SOllivier Robert exec @plotcmd; 266c0b746e5SOllivier Robert die("$0: failed to exec (@plotcmd): $!\n"); 267c0b746e5SOllivier Robert exit(1); # in case ... 268c0b746e5SOllivier Robert} 269c0b746e5SOllivier Robert 270c0b746e5SOllivier Robertsub read_config 271c0b746e5SOllivier Robert{ 272c0b746e5SOllivier Robert local($at) = (stat($config))[$[+9]; 273c0b746e5SOllivier Robert local($_,$c,$v); 274c0b746e5SOllivier Robert 275c0b746e5SOllivier Robert (undef($laststat),(print("stat $config failed: $!\n")),return) if ! defined($at); 276c0b746e5SOllivier Robert return if (defined($laststat) && ($laststat == $at)); 277c0b746e5SOllivier Robert $laststat = $at; 278c0b746e5SOllivier Robert 279c0b746e5SOllivier Robert print "reading configuration from \"$config\"\n" if $verbose; 280c0b746e5SOllivier Robert 281c0b746e5SOllivier Robert open(CF,"<$config") || 282c0b746e5SOllivier Robert (warn("$0: failed to read \"$config\" - using old settings ($!)\n"), 283c0b746e5SOllivier Robert return); 284c0b746e5SOllivier Robert while(<CF>) 285c0b746e5SOllivier Robert { 286c0b746e5SOllivier Robert chop; 287c0b746e5SOllivier Robert s/^([^\#]*[^\#\s]?)\s*\#.*$//; 288c0b746e5SOllivier Robert next if /^\s*$/; 289c0b746e5SOllivier Robert 290c0b746e5SOllivier Robert s/^\s*([^=\s]*)\s*=\s*(.*\S)\s*$/$1=$2/; 291c0b746e5SOllivier Robert 292c0b746e5SOllivier Robert ($c,$v) = split(/=/,$_,2); 293c0b746e5SOllivier Robert print "processing \"$c=$v\"\n" if $verbose > 3; 294c0b746e5SOllivier Robert ($c eq "delay") && ($delay = $v,1) && next; 295c0b746e5SOllivier Robert ($c eq 'samples') && (!defined($PrintIt) || !defined($samples)) && 296c0b746e5SOllivier Robert ($samples = $v,1) && next; 297c0b746e5SOllivier Robert ($c eq 'srcprefix') && (($srcprefix=$v)=~s/\$STATHOST/$STATHOST/g,1) 298c0b746e5SOllivier Robert && next; 299c0b746e5SOllivier Robert ($c eq 'showoffs') && 300c0b746e5SOllivier Robert ($showoffs = boolval($v),1) && next; 301c0b746e5SOllivier Robert ($c eq 'showfreq') && 302c0b746e5SOllivier Robert ($showfreq = boolval($v),1) && next; 303c0b746e5SOllivier Robert ($c eq 'showcmpl') && 304c0b746e5SOllivier Robert ($showcmpl = boolval($v),1) && next; 305c0b746e5SOllivier Robert ($c eq 'showoreg') && 306c0b746e5SOllivier Robert ($showoreg = boolval($v),1) && next; 307c0b746e5SOllivier Robert ($c eq 'showfreg') && 308c0b746e5SOllivier Robert ($showfreg = boolval($v),1) && next; 309c0b746e5SOllivier Robert 310c0b746e5SOllivier Robert ($c eq 'exit') && (unlink($tmpfile),die("$0: exit by config request\n")); 311c0b746e5SOllivier Robert 312c0b746e5SOllivier Robert ($c eq 'freqbase' || 313c0b746e5SOllivier Robert $c eq 'cmplscale') && 314c0b746e5SOllivier Robert do { 315c0b746e5SOllivier Robert if (! defined($v) || $v eq "" || $v eq 'dynamic') 316c0b746e5SOllivier Robert { 317c0b746e5SOllivier Robert eval "undef(\$$c);"; 318c0b746e5SOllivier Robert } 319c0b746e5SOllivier Robert else 320c0b746e5SOllivier Robert { 321c0b746e5SOllivier Robert eval "\$$c = \$v;"; 322c0b746e5SOllivier Robert } 323c0b746e5SOllivier Robert next; 324c0b746e5SOllivier Robert }; 325c0b746e5SOllivier Robert ($c eq 'timebase') && 326c0b746e5SOllivier Robert do { 327c0b746e5SOllivier Robert if (! defined($v) || $v eq "" || $v eq "dynamic") 328c0b746e5SOllivier Robert { 329c0b746e5SOllivier Robert undef($timebase); 330c0b746e5SOllivier Robert } 331c0b746e5SOllivier Robert else 332c0b746e5SOllivier Robert { 333c0b746e5SOllivier Robert $timebase=&date_time_spec2seconds($v); 334c0b746e5SOllivier Robert } 335c0b746e5SOllivier Robert }; 336c0b746e5SOllivier Robert ($c eq 'EndTime') && 337c0b746e5SOllivier Robert do { 338c0b746e5SOllivier Robert next if defined($EndTime) && defined($PrintIt); 339c0b746e5SOllivier Robert if (! defined($v) || $v eq "" || $v eq "none") 340c0b746e5SOllivier Robert { 341c0b746e5SOllivier Robert undef($EndTime); 342c0b746e5SOllivier Robert } 343c0b746e5SOllivier Robert else 344c0b746e5SOllivier Robert { 345c0b746e5SOllivier Robert $EndTime=&date_time_spec2seconds($v); 346c0b746e5SOllivier Robert } 347c0b746e5SOllivier Robert }; 348c0b746e5SOllivier Robert ($c eq 'StartTime') && 349c0b746e5SOllivier Robert do { 350c0b746e5SOllivier Robert next if defined($StartTime) && defined($PrintIt); 351c0b746e5SOllivier Robert if (! defined($v) || $v eq "" || $v eq "none") 352c0b746e5SOllivier Robert { 353c0b746e5SOllivier Robert undef($StartTime); 354c0b746e5SOllivier Robert } 355c0b746e5SOllivier Robert else 356c0b746e5SOllivier Robert { 357c0b746e5SOllivier Robert $StartTime=&date_time_spec2seconds($v); 358c0b746e5SOllivier Robert } 359c0b746e5SOllivier Robert }; 360c0b746e5SOllivier Robert 361c0b746e5SOllivier Robert ($c eq 'MaxY') && 362c0b746e5SOllivier Robert do { 363c0b746e5SOllivier Robert next if defined($MaxY) && defined($PrintIt); 364c0b746e5SOllivier Robert if (! defined($v) || $v eq "" || $v eq "none") 365c0b746e5SOllivier Robert { 366c0b746e5SOllivier Robert undef($MaxY); 367c0b746e5SOllivier Robert } 368c0b746e5SOllivier Robert else 369c0b746e5SOllivier Robert { 370c0b746e5SOllivier Robert $MaxY=$v; 371c0b746e5SOllivier Robert } 372c0b746e5SOllivier Robert }; 373c0b746e5SOllivier Robert 374c0b746e5SOllivier Robert ($c eq 'MinY') && 375c0b746e5SOllivier Robert do { 376c0b746e5SOllivier Robert next if defined($MinY) && defined($PrintIt); 377c0b746e5SOllivier Robert if (! defined($v) || $v eq "" || $v eq "none") 378c0b746e5SOllivier Robert { 379c0b746e5SOllivier Robert undef($MinY); 380c0b746e5SOllivier Robert } 381c0b746e5SOllivier Robert else 382c0b746e5SOllivier Robert { 383c0b746e5SOllivier Robert $MinY=$v; 384c0b746e5SOllivier Robert } 385c0b746e5SOllivier Robert }; 386c0b746e5SOllivier Robert 387c0b746e5SOllivier Robert ($c eq 'deltaT') && 388c0b746e5SOllivier Robert do { 389c0b746e5SOllivier Robert if (!defined($v) || $v eq "") 390c0b746e5SOllivier Robert { 391c0b746e5SOllivier Robert undef($deltaT); 392c0b746e5SOllivier Robert } 393c0b746e5SOllivier Robert else 394c0b746e5SOllivier Robert { 395c0b746e5SOllivier Robert $deltaT = $v; 396c0b746e5SOllivier Robert } 397c0b746e5SOllivier Robert next; 398c0b746e5SOllivier Robert }; 399c0b746e5SOllivier Robert ($c eq 'verbose') && ! defined($PrintIt) && 400c0b746e5SOllivier Robert do { 401c0b746e5SOllivier Robert if (!defined($v) || $v == 0) 402c0b746e5SOllivier Robert { 403c0b746e5SOllivier Robert $verbose = 0; 404c0b746e5SOllivier Robert } 405c0b746e5SOllivier Robert else 406c0b746e5SOllivier Robert { 407c0b746e5SOllivier Robert $verbose = $v; 408c0b746e5SOllivier Robert } 409c0b746e5SOllivier Robert next; 410c0b746e5SOllivier Robert }; 411c0b746e5SOllivier Robert ;# otherwise: silently ignore unrecognized config line 412c0b746e5SOllivier Robert } 413c0b746e5SOllivier Robert close(CF); 414c0b746e5SOllivier Robert ;# set show defaults when nothing selected 415c0b746e5SOllivier Robert $showoffs = $showfreq = $showcmpl = 1 416c0b746e5SOllivier Robert unless $showoffs || $showfreq || $showcmpl; 417c0b746e5SOllivier Robert if ($verbose > 3) 418c0b746e5SOllivier Robert { 419c0b746e5SOllivier Robert print "new configuration:\n"; 420c0b746e5SOllivier Robert print " delay\t= $delay\n"; 421c0b746e5SOllivier Robert print " samples\t= $samples\n"; 422c0b746e5SOllivier Robert print " srcprefix\t= $srcprefix\n"; 423c0b746e5SOllivier Robert print " showoffs\t= $showoffs\n"; 424c0b746e5SOllivier Robert print " showfreq\t= $showfreq\n"; 425c0b746e5SOllivier Robert print " showcmpl\t= $showcmpl\n"; 426c0b746e5SOllivier Robert print " showoreg\t= $showoreg\n"; 427c0b746e5SOllivier Robert print " showfreg\t= $showfreg\n"; 428c0b746e5SOllivier Robert printf " timebase\t= %s",defined($timebase)?&ctime($timebase):"dynamic\n"; 429c0b746e5SOllivier Robert printf " freqbase\t= %s\n",defined($freqbase) ?"$freqbase":"dynamic"; 430c0b746e5SOllivier Robert printf " cmplscale\t= %s\n",defined($cmplscale)?"$cmplscale":"dynamic"; 431c0b746e5SOllivier Robert printf " StartTime\t= %s",defined($StartTime)?&ctime($StartTime):"none\n"; 432c0b746e5SOllivier Robert printf " EndTime\t= %s", defined($EndTime) ? &ctime($EndTime):"none\n"; 433c0b746e5SOllivier Robert printf " MaxY\t= %s",defined($MaxY)? $MaxY :"none\n"; 434c0b746e5SOllivier Robert printf " MinY\t= %s",defined($MinY)? $MinY :"none\n"; 435c0b746e5SOllivier Robert print " verbose\t= $verbose\n"; 436c0b746e5SOllivier Robert } 437c0b746e5SOllivier Robertprint "configuration file read\n" if $verbose > 2; 438c0b746e5SOllivier Robert} 439c0b746e5SOllivier Robert 440ea906c41SOllivier Robertsub make_doplot($$) 441c0b746e5SOllivier Robert{ 442ea906c41SOllivier Robert my($lo, $lf) = @_; 443c0b746e5SOllivier Robert local($c) = (""); 444c0b746e5SOllivier Robert local($fmt) 445c0b746e5SOllivier Robert = ("%s \"%s\" using 1:%d title '%s <%lf %lf> %6s' with lines"); 446c0b746e5SOllivier Robert local($regfmt) 447c0b746e5SOllivier Robert = ("%s ((%lf * x) + %lf) title 'lin. approx. %s (%f t[h]) %s %f <%f> %6s' with lines"); 448c0b746e5SOllivier Robert 449c0b746e5SOllivier Robert $doplot = " set title 'NTP loopfilter statistics for $STATHOST " . 450c0b746e5SOllivier Robert "(last $LastCnt samples from $srcprefix*)'\n"; 451c0b746e5SOllivier Robert 452c0b746e5SOllivier Robert local($xts,$xte,$i,$t); 453c0b746e5SOllivier Robert 454c0b746e5SOllivier Robert local($s,$c) = (""); 455c0b746e5SOllivier Robert 456c0b746e5SOllivier Robert ;# number of integral seconds to get at least 12 tic marks on x axis 457c0b746e5SOllivier Robert $t = int(($maxtime - $mintime) / 12 + 0.5); 458c0b746e5SOllivier Robert $t = 1 unless $t; # prevent $t to be zero 459c0b746e5SOllivier Robert foreach $i (30, 460c0b746e5SOllivier Robert 60,5*60,15*60,30*60, 461c0b746e5SOllivier Robert 60*60,2*60*60,6*60*60,12*60*60, 462c0b746e5SOllivier Robert 24*60*60,48*60*60) 463c0b746e5SOllivier Robert { 464c0b746e5SOllivier Robert last if $t < $i; 465c0b746e5SOllivier Robert $t = $t - ($t % $i); 466c0b746e5SOllivier Robert } 467c0b746e5SOllivier Robert print "time label resolution: $t seconds\n" if $verbose > 1; 468c0b746e5SOllivier Robert 469c0b746e5SOllivier Robert ;# make gnuplot use wall clock time labels instead of NTP seconds 470c0b746e5SOllivier Robert for ($c="", $i = $mintime - ($mintime % $t); 471c0b746e5SOllivier Robert $i <= $maxtime + $t; 472c0b746e5SOllivier Robert $i += $t, $c=",") 473c0b746e5SOllivier Robert { 474c0b746e5SOllivier Robert $s .= $c; 475c0b746e5SOllivier Robert ((int($i / $t) % 2) && 476c0b746e5SOllivier Robert ($s .= sprintf("'' %lf",($i - $LastTimeBase)/3600))) || 477c0b746e5SOllivier Robert (($t <= 60) && 478c0b746e5SOllivier Robert ($s .= sprintf("'%d:%02d:%02d' %lf", 479c0b746e5SOllivier Robert (localtime($i))[$[+2,$[+1,$[+0], 480c0b746e5SOllivier Robert ($i - $LastTimeBase)/3600))) 481c0b746e5SOllivier Robert || (($t <= 2*60*60) && 482c0b746e5SOllivier Robert ($s .= sprintf("'%d:%02d' %lf", 483c0b746e5SOllivier Robert (localtime($i))[$[+2,$[+1], 484c0b746e5SOllivier Robert ($i - $LastTimeBase)/3600))) 485c0b746e5SOllivier Robert || (($t <= 12*60*60) && 486c0b746e5SOllivier Robert ($s .= sprintf("'%s %d:00' %lf", 487c0b746e5SOllivier Robert $Day[(localtime($i))[$[+6]], 488c0b746e5SOllivier Robert (localtime($i))[$[+2], 489c0b746e5SOllivier Robert ($i - $LastTimeBase)/3600))) 490c0b746e5SOllivier Robert || ($s .= sprintf("'%d.%d-%d:00' %lf", 491c0b746e5SOllivier Robert (localtime($i))[$[+3,$[+4,$[+2], 492c0b746e5SOllivier Robert ($i - $LastTimeBase)/3600)); 493c0b746e5SOllivier Robert } 494c0b746e5SOllivier Robert $doplot .= "set xtics ($s)\n"; 495c0b746e5SOllivier Robert 496c0b746e5SOllivier Robert chop($xts = &ctime($mintime)); 497c0b746e5SOllivier Robert chop($xte = &ctime($maxtime)); 498c0b746e5SOllivier Robert $doplot .= "set xlabel 'Start: $xts -- Time Scale -- End: $xte'\n"; 499c0b746e5SOllivier Robert $doplot .= "set yrange [" ; 500c0b746e5SOllivier Robert $doplot .= defined($MinY) ? sprintf("%lf", $MinY) : $miny; 501c0b746e5SOllivier Robert $doplot .= ':'; 502c0b746e5SOllivier Robert $doplot .= defined($MaxY) ? sprintf("%lf", $MaxY) : $maxy; 503c0b746e5SOllivier Robert $doplot .= "]\n"; 504c0b746e5SOllivier Robert 505c0b746e5SOllivier Robert $doplot .= " plot"; 506c0b746e5SOllivier Robert $c = ""; 507c0b746e5SOllivier Robert $showoffs && 508c0b746e5SOllivier Robert ($doplot .= sprintf($fmt,$c,$tmpfile,2, 509c0b746e5SOllivier Robert "offset", 510c0b746e5SOllivier Robert $minoffs,$maxoffs, 511c0b746e5SOllivier Robert "[ms]"), 512c0b746e5SOllivier Robert $c = ","); 513c0b746e5SOllivier Robert $LastCmplScale = 1 if ! defined($LastCmplScale); 514c0b746e5SOllivier Robert $showcmpl && 515c0b746e5SOllivier Robert ($doplot .= sprintf($fmt,$c,$tmpfile,4, 516c0b746e5SOllivier Robert "compliance" . 517c0b746e5SOllivier Robert (&abs($LastCmplScale) > 1 518c0b746e5SOllivier Robert ? " / $LastCmplScale" 519c0b746e5SOllivier Robert : (&abs($LastCmplScale) == 1 ? "" : " * ".(1/$LastCmplScale))), 520c0b746e5SOllivier Robert $mincmpl/$LastCmplScale,$maxcmpl/$LastCmplScale, 521c0b746e5SOllivier Robert ""), 522c0b746e5SOllivier Robert $c = ","); 523c0b746e5SOllivier Robert $LastFreqBase = 0 if ! defined($LastFreqBase); 524c0b746e5SOllivier Robert $LastFreqBaseString = "?" if ! defined($LastFreqBaseString); 525c0b746e5SOllivier Robert $FreqScale = 1 if ! defined($FreqScale); 526c0b746e5SOllivier Robert $FreqScaleInv = 1 if ! defined($FreqScaleInv); 527c0b746e5SOllivier Robert $showfreq && 528c0b746e5SOllivier Robert ($doplot .= sprintf($fmt,$c,$tmpfile,3, 529c0b746e5SOllivier Robert "frequency" . 530c0b746e5SOllivier Robert ($LastFreqBase > 0 531c0b746e5SOllivier Robert ? " - $LastFreqBaseString" 532c0b746e5SOllivier Robert : ($LastFreqBase == 0 ? "" : " + $LastFreqBaseString")), 533c0b746e5SOllivier Robert $minfreq * $FreqScale - $LastFreqBase, 534c0b746e5SOllivier Robert $maxfreq * $FreqScale - $LastFreqBase, 535c0b746e5SOllivier Robert "[${FreqScaleInv}ppm]"), 536c0b746e5SOllivier Robert $c = ","); 537c0b746e5SOllivier Robert $showoreg && $showoffs && 538c0b746e5SOllivier Robert ($doplot .= sprintf($regfmt, $c, 539ea906c41SOllivier Robert $lo->B(),$lo->A(), 540c0b746e5SOllivier Robert "offset ", 541ea906c41SOllivier Robert $lo->B(), 542ea906c41SOllivier Robert (($lo->A()) < 0 ? '-' : '+'), 543ea906c41SOllivier Robert &abs($lo->A()), $lo->r(), 544c0b746e5SOllivier Robert "[ms]"), 545c0b746e5SOllivier Robert $c = ","); 546c0b746e5SOllivier Robert $showfreg && $showfreq && 547c0b746e5SOllivier Robert ($doplot .= sprintf($regfmt, $c, 548ea906c41SOllivier Robert $lf->B() * $FreqScale, 549ea906c41SOllivier Robert ($lf->A() + $minfreq) * $FreqScale - $LastFreqBase, 550c0b746e5SOllivier Robert "frequency", 551ea906c41SOllivier Robert $lf->B() * $FreqScale, 552ea906c41SOllivier Robert (($lf->A() + $minfreq) * $FreqScale - $LastFreqBase) < 0 ? '-' : '+', 553ea906c41SOllivier Robert &abs(($lf->A() + $minfreq) * $FreqScale - $LastFreqBase), 554ea906c41SOllivier Robert $lf->r(), 555c0b746e5SOllivier Robert "[${FreqScaleInv}ppm]"), 556c0b746e5SOllivier Robert $c = ","); 557c0b746e5SOllivier Robert $doplot .= "\n"; 558c0b746e5SOllivier Robert} 559c0b746e5SOllivier Robert 560c0b746e5SOllivier Robert%F_key = (); 561c0b746e5SOllivier Robert%F_name = (); 562c0b746e5SOllivier Robert%F_size = (); 563c0b746e5SOllivier Robert%F_mtime = (); 564c0b746e5SOllivier Robert%F_first = (); 565c0b746e5SOllivier Robert%F_last = (); 566c0b746e5SOllivier Robert 567c0b746e5SOllivier Robertsub genfile 568c0b746e5SOllivier Robert{ 569ea906c41SOllivier Robert local($cnt,$in,$out,$lo,$lf,@fpos) = @_; 570c0b746e5SOllivier Robert 571c0b746e5SOllivier Robert local(@F,@t,$t,$lastT) = (); 572c0b746e5SOllivier Robert local(@break,@time,@offs,@freq,@cmpl,@loffset,@filekey) = (); 573c0b746e5SOllivier Robert local($lm,$l,@f); 574c0b746e5SOllivier Robert 575c0b746e5SOllivier Robert local($sdir,$sname); 576c0b746e5SOllivier Robert 577c0b746e5SOllivier Robert ;# allocate some storage for the tables 578c0b746e5SOllivier Robert ;# otherwise realloc may get into troubles 579c0b746e5SOllivier Robert if (defined($StartTime) && defined($EndTime)) 580c0b746e5SOllivier Robert { 581c0b746e5SOllivier Robert $l = ($EndTime-$StartTime) -$[+1 +1; # worst case: 1 sample per second 582c0b746e5SOllivier Robert } 583c0b746e5SOllivier Robert else 584c0b746e5SOllivier Robert { 585c0b746e5SOllivier Robert $l = $cnt + 10; 586c0b746e5SOllivier Robert } 587c0b746e5SOllivier Robert print "preextending arrays to $l entries\n" if $verbose > 2; 588c0b746e5SOllivier Robert $#break = $l; for ($i=$[; $i<=$l;$i++) { $break[$i] = 0; } 589c0b746e5SOllivier Robert $#time = $l; for ($i=$[; $i<=$l;$i++) { $time[$i] = 0; } 590c0b746e5SOllivier Robert $#offs = $l; for ($i=$[; $i<=$l;$i++) { $offs[$i] = 0; } 591c0b746e5SOllivier Robert $#freq = $l; for ($i=$[; $i<=$l;$i++) { $freq[$i] = 0; } 592c0b746e5SOllivier Robert $#cmpl = $l; for ($i=$[; $i<=$l;$i++) { $cmpl[$i] = 0; } 593c0b746e5SOllivier Robert $#loffset = $l; for ($i=$[; $i<=$l;$i++) { $loffset[$i] = 0; } 594c0b746e5SOllivier Robert $#filekey = $l; for ($i=$[; $i<=$l;$i++) { $filekey[$i] = 0; } 595c0b746e5SOllivier Robert ;# now reduce size again 596c0b746e5SOllivier Robert $#break = $[ - 1; 597c0b746e5SOllivier Robert $#time = $[ - 1; 598c0b746e5SOllivier Robert $#offs = $[ - 1; 599c0b746e5SOllivier Robert $#freq = $[ - 1; 600c0b746e5SOllivier Robert $#cmpl = $[ - 1; 601c0b746e5SOllivier Robert $#loffset = $[ - 1; 602c0b746e5SOllivier Robert $#filekey = $[ - 1; 603c0b746e5SOllivier Robert print "memory allocation ready\n" if $verbose > 2; 604c0b746e5SOllivier Robert sleep(3) if $verbose > 1; 605c0b746e5SOllivier Robert 606c0b746e5SOllivier Robert $fpos[$[] = '' if !defined($fpos[$[]); 607c0b746e5SOllivier Robert 608c0b746e5SOllivier Robert if (index($in,"/") < $[) 609c0b746e5SOllivier Robert { 610c0b746e5SOllivier Robert $sdir = "."; 611c0b746e5SOllivier Robert $sname = $in; 612c0b746e5SOllivier Robert } 613c0b746e5SOllivier Robert else 614c0b746e5SOllivier Robert { 615c0b746e5SOllivier Robert ($sdir,$sname) = ($in =~ m!^(.*)/([^/]*)!); 616c0b746e5SOllivier Robert $sname = "" unless defined($sname); 617c0b746e5SOllivier Robert } 618c0b746e5SOllivier Robert 619c0b746e5SOllivier Robert $Ltime = -1 if ! defined($Ltime); 620c0b746e5SOllivier Robert if (!defined($Lsdir) || $Lsdir ne $sdir || $Ltime != (stat($sdir))[$[+9] || 621c0b746e5SOllivier Robert grep($F_mtime{$_} != (stat($F_name{$_}))[$[+9], @F_files)) 622c0b746e5SOllivier Robert 623c0b746e5SOllivier Robert { 624c0b746e5SOllivier Robert print "rescanning directory \"$sdir\" for files \"$sname*\"\n" 625c0b746e5SOllivier Robert if $verbose > 1; 626c0b746e5SOllivier Robert 627c0b746e5SOllivier Robert ;# rescan directory on changes 628c0b746e5SOllivier Robert $Lsdir = $sdir; 629c0b746e5SOllivier Robert $Ltime = (stat($sdir))[$[+9]; 630c0b746e5SOllivier Robert </X{> if 0; # dummy line - calm down my formatter 631c0b746e5SOllivier Robert local(@newfiles) = < ${in}*[0-9] >; 632c0b746e5SOllivier Robert local($st_dev,$st_ino,$st_mtime,$st_size,$name,$key,$modified); 633c0b746e5SOllivier Robert 634c0b746e5SOllivier Robert foreach $name (@newfiles) 635c0b746e5SOllivier Robert { 636c0b746e5SOllivier Robert ($st_dev,$st_ino,$st_size,$st_mtime) = 637c0b746e5SOllivier Robert (stat($name))[$[,$[+1,$[+7,$[+9]; 638c0b746e5SOllivier Robert $modified = 0; 639c0b746e5SOllivier Robert $key = sprintf("%lx|%lu", $st_dev, $st_ino); 640c0b746e5SOllivier Robert 641c0b746e5SOllivier Robert print "candidate file \"$name\"", 642c0b746e5SOllivier Robert (defined($st_dev) ? "" : " failed: $!"),"\n" 643c0b746e5SOllivier Robert if $verbose > 2; 644c0b746e5SOllivier Robert 645c0b746e5SOllivier Robert if (! defined($F_key{$name}) || $F_key{$name} ne $key) 646c0b746e5SOllivier Robert { 647c0b746e5SOllivier Robert $F_key{$name} = $key; 648c0b746e5SOllivier Robert $modified++; 649c0b746e5SOllivier Robert } 650c0b746e5SOllivier Robert if (!defined($F_name{$key}) || $F_name{$key} ne $name) 651c0b746e5SOllivier Robert { 652c0b746e5SOllivier Robert $F_name{$key} = $name; 653c0b746e5SOllivier Robert $modified++; 654c0b746e5SOllivier Robert } 655c0b746e5SOllivier Robert if (!defined($F_size{$key}) || $F_size{$key} != $st_size) 656c0b746e5SOllivier Robert { 657c0b746e5SOllivier Robert $F_size{$key} = $st_size; 658c0b746e5SOllivier Robert $modified++; 659c0b746e5SOllivier Robert } 660c0b746e5SOllivier Robert if (!defined($F_mtime{$key}) || $F_mtime{$key} != $st_mtime) 661c0b746e5SOllivier Robert { 662c0b746e5SOllivier Robert $F_mtime{$key} = $st_mtime; 663c0b746e5SOllivier Robert $modified++; 664c0b746e5SOllivier Robert } 665c0b746e5SOllivier Robert if ($modified) 666c0b746e5SOllivier Robert { 667c0b746e5SOllivier Robert print "new data \"$name\" key: $key;\n" if $verbose > 1; 668c0b746e5SOllivier Robert print " size: $st_size; mtime: $st_mtime;\n" 669c0b746e5SOllivier Robert if $verbose > 1; 670c0b746e5SOllivier Robert $F_last{$key} = $F_first{$key} = $st_mtime; 671c0b746e5SOllivier Robert $F_first{$key}--; # prevent zero divide later on 672c0b746e5SOllivier Robert ;# now compute derivated attributes 673c0b746e5SOllivier Robert open(IN, "<$name") || 674c0b746e5SOllivier Robert do { 675c0b746e5SOllivier Robert warn "$0: failed to open \"$name\": $!"; 676c0b746e5SOllivier Robert next; 677c0b746e5SOllivier Robert }; 678c0b746e5SOllivier Robert 679c0b746e5SOllivier Robert while(<IN>) 680c0b746e5SOllivier Robert { 681c0b746e5SOllivier Robert @F = split; 682c0b746e5SOllivier Robert next if @F < 5; 683c0b746e5SOllivier Robert next if $F[$[] eq ""; 684c0b746e5SOllivier Robert $t = ($F[$[] - $MJD_1970) * 24 * 60 * 60; 685c0b746e5SOllivier Robert $t += $F[$[+1]; 686c0b746e5SOllivier Robert $F_first{$key} = $t; 687c0b746e5SOllivier Robert print "\tfound first entry: $t ",&ctime($t) 688c0b746e5SOllivier Robert if $verbose > 4; 689c0b746e5SOllivier Robert last; 690c0b746e5SOllivier Robert } 691c0b746e5SOllivier Robert seek(IN, 692c0b746e5SOllivier Robert ($st_size > 4*$RecordSize) ? $st_size - 4*$RecordSize : 0, 693c0b746e5SOllivier Robert 0); 694c0b746e5SOllivier Robert while(<IN>) 695c0b746e5SOllivier Robert { 696c0b746e5SOllivier Robert @F = split; 697c0b746e5SOllivier Robert next if @F < 5; 698c0b746e5SOllivier Robert next if $F[$[] eq ""; 699c0b746e5SOllivier Robert $t = ($F[$[] - $MJD_1970) * 24 * 60 * 60; 700c0b746e5SOllivier Robert $t += $F[$[+1]; 701c0b746e5SOllivier Robert $F_last{$key} = $t; 702c0b746e5SOllivier Robert $_ = <IN>; 703c0b746e5SOllivier Robert print "\tfound last entry: $t ", &ctime($t) 704c0b746e5SOllivier Robert if $verbose > 4 && ! defined($_); 705c0b746e5SOllivier Robert last unless defined($_); 706c0b746e5SOllivier Robert redo; 707c0b746e5SOllivier Robert ;# Ok, calm down... 708c0b746e5SOllivier Robert ;# using $_ = <IN> in conjunction with redo 709c0b746e5SOllivier Robert ;# is semantically equivalent to the while loop, but 710c0b746e5SOllivier Robert ;# I needed a one line look ahead and this solution 711c0b746e5SOllivier Robert ;# was what I thought of first 712c0b746e5SOllivier Robert ;# and.. If you do not like it dont look 713c0b746e5SOllivier Robert } 714c0b746e5SOllivier Robert close(IN); 715c0b746e5SOllivier Robert print(" first: ",$F_first{$key}, 716c0b746e5SOllivier Robert " last: ",$F_last{$key},"\n") if $verbose > 1; 717c0b746e5SOllivier Robert } 718c0b746e5SOllivier Robert } 719c0b746e5SOllivier Robert ;# now reclaim memory used for files no longer referenced ... 720c0b746e5SOllivier Robert local(%Names); 721c0b746e5SOllivier Robert grep($Names{$_} = 1,@newfiles); 722c0b746e5SOllivier Robert foreach (keys %F_key) 723c0b746e5SOllivier Robert { 724c0b746e5SOllivier Robert next if defined($Names{$_}); 725c0b746e5SOllivier Robert delete $F_key{$_}; 726c0b746e5SOllivier Robert $verbose > 2 && print "no longer referenced: \"$_\"\n"; 727c0b746e5SOllivier Robert } 728c0b746e5SOllivier Robert %Names = (); 729c0b746e5SOllivier Robert 730c0b746e5SOllivier Robert grep($Names{$_} = 1,values(%F_key)); 731c0b746e5SOllivier Robert foreach (keys %F_name) 732c0b746e5SOllivier Robert { 733c0b746e5SOllivier Robert next if defined($Names{$_}); 734c0b746e5SOllivier Robert delete $F_name{$_}; 735c0b746e5SOllivier Robert $verbose > 2 && print "unref name($_)= $F_name{$_}\n"; 736c0b746e5SOllivier Robert } 737c0b746e5SOllivier Robert foreach (keys %F_size) 738c0b746e5SOllivier Robert { 739c0b746e5SOllivier Robert next if defined($Names{$_}); 740c0b746e5SOllivier Robert delete $F_size{$_}; 741c0b746e5SOllivier Robert $verbose > 2 && print "unref size($_)\n"; 742c0b746e5SOllivier Robert } 743c0b746e5SOllivier Robert foreach (keys %F_mtime) 744c0b746e5SOllivier Robert { 745c0b746e5SOllivier Robert next if defined($Names{$_}); 746c0b746e5SOllivier Robert delete $F_mtime{$_}; 747c0b746e5SOllivier Robert $verbose > 2 && print "unref mtime($_)\n"; 748c0b746e5SOllivier Robert } 749c0b746e5SOllivier Robert foreach (keys %F_first) 750c0b746e5SOllivier Robert { 751c0b746e5SOllivier Robert next if defined($Names{$_}); 752c0b746e5SOllivier Robert delete $F_first{$_}; 753c0b746e5SOllivier Robert $verbose > 2 && print "unref first($_)\n"; 754c0b746e5SOllivier Robert } 755c0b746e5SOllivier Robert foreach (keys %F_last) 756c0b746e5SOllivier Robert { 757c0b746e5SOllivier Robert next if defined($Names{$_}); 758c0b746e5SOllivier Robert delete $F_last{$_}; 759c0b746e5SOllivier Robert $verbose > 2 && print "unref last($_)\n"; 760c0b746e5SOllivier Robert } 761c0b746e5SOllivier Robert ;# create list sorted by time 762c0b746e5SOllivier Robert @F_files = sort {$F_first{$a} <=> $F_first{$b}; } keys(%F_name); 763c0b746e5SOllivier Robert if ($verbose > 1) 764c0b746e5SOllivier Robert { 765c0b746e5SOllivier Robert print "Resulting file list:\n"; 766c0b746e5SOllivier Robert foreach (@F_files) 767c0b746e5SOllivier Robert { 768c0b746e5SOllivier Robert print "\t$_\t$F_name{$_}\n"; 769c0b746e5SOllivier Robert } 770c0b746e5SOllivier Robert } 771c0b746e5SOllivier Robert } 772c0b746e5SOllivier Robert 773c0b746e5SOllivier Robert printf("processing %s; output \"$out\" (%d input files)\n", 774c0b746e5SOllivier Robert ((defined($StartTime) && defined($EndTime)) 775c0b746e5SOllivier Robert ? "time range" 776c0b746e5SOllivier Robert : (defined($StartTime) ? "$cnt samples from StartTime" : 777c0b746e5SOllivier Robert (defined($EndTime) ? "$cnt samples to EndTime" : 778c0b746e5SOllivier Robert "last $cnt samples"))), 779c0b746e5SOllivier Robert scalar(@F_files)) 780c0b746e5SOllivier Robert if $verbose > 1; 781c0b746e5SOllivier Robert 782c0b746e5SOllivier Robert ;# open output file - will be input for plotcmd 783c0b746e5SOllivier Robert open(OUT,">$out") || 784c0b746e5SOllivier Robert do { 785c0b746e5SOllivier Robert warn("$0: cannot create \"$out\": $!\n"); 786c0b746e5SOllivier Robert }; 787c0b746e5SOllivier Robert 788c0b746e5SOllivier Robert @f = @F_files; 789c0b746e5SOllivier Robert if (defined($StartTime)) 790c0b746e5SOllivier Robert { 791c0b746e5SOllivier Robert while (@f && ($F_last{$f[$[]} < $StartTime)) 792c0b746e5SOllivier Robert { 793c0b746e5SOllivier Robert print("shifting ", $F_name{$f[$[]}, 794c0b746e5SOllivier Robert " last: ", $F_last{$f[$[]}, 795c0b746e5SOllivier Robert " < StartTime: $StartTime\n") 796c0b746e5SOllivier Robert if $verbose > 3; 797c0b746e5SOllivier Robert shift(@f); 798c0b746e5SOllivier Robert } 799c0b746e5SOllivier Robert 800c0b746e5SOllivier Robert 801c0b746e5SOllivier Robert } 802c0b746e5SOllivier Robert if (defined($EndTime)) 803c0b746e5SOllivier Robert { 804c0b746e5SOllivier Robert while (@f && ($F_first{$f[$#f]} > $EndTime)) 805c0b746e5SOllivier Robert { 806c0b746e5SOllivier Robert print("popping ", $F_name{$f[$#f]}, 807c0b746e5SOllivier Robert " first: ", $F_first{$f[$#f]}, 808c0b746e5SOllivier Robert " > EndTime: $EndTime\n") 809c0b746e5SOllivier Robert if $verbose > 3; 810c0b746e5SOllivier Robert pop(@f); 811c0b746e5SOllivier Robert } 812c0b746e5SOllivier Robert } 813c0b746e5SOllivier Robert 814c0b746e5SOllivier Robert if (@f) 815c0b746e5SOllivier Robert { 816c0b746e5SOllivier Robert if (defined($StartTime)) 817c0b746e5SOllivier Robert { 818c0b746e5SOllivier Robert print "guess start according to StartTime ($StartTime)\n" 819c0b746e5SOllivier Robert if $verbose > 3; 820c0b746e5SOllivier Robert 821c0b746e5SOllivier Robert if ($fpos[$[] eq 'start') 822c0b746e5SOllivier Robert { 823c0b746e5SOllivier Robert if (grep($_ eq $fpos[$[+1],@f)) 824c0b746e5SOllivier Robert { 825c0b746e5SOllivier Robert shift(@f) while @f && $f[$[] ne $fpos[$[+1]; 826c0b746e5SOllivier Robert } 827c0b746e5SOllivier Robert else 828c0b746e5SOllivier Robert { 829c0b746e5SOllivier Robert @fpos = ('start', $f[$[], undef); 830c0b746e5SOllivier Robert } 831c0b746e5SOllivier Robert } 832c0b746e5SOllivier Robert else 833c0b746e5SOllivier Robert { 834c0b746e5SOllivier Robert @fpos = ('start' , $f[$[], undef); 835c0b746e5SOllivier Robert } 836c0b746e5SOllivier Robert 837c0b746e5SOllivier Robert if (!defined($fpos[$[+2])) 838c0b746e5SOllivier Robert { 839c0b746e5SOllivier Robert if ($StartTime <= $F_first{$f[$[]}) 840c0b746e5SOllivier Robert { 841c0b746e5SOllivier Robert $fpos[$[+2] = 0; 842c0b746e5SOllivier Robert } 843c0b746e5SOllivier Robert else 844c0b746e5SOllivier Robert { 845c0b746e5SOllivier Robert $fpos[$[+2] = 846c0b746e5SOllivier Robert int($F_size{$f[$[]} * 847c0b746e5SOllivier Robert (($StartTime - $F_first{$f[$[]})/ 848c0b746e5SOllivier Robert ($F_last{$f[$[]} - $F_first{$f[$[]}))); 849c0b746e5SOllivier Robert $fpos[$[+2] = ($fpos[$[+2] <= 2 * $RecordSize) 850c0b746e5SOllivier Robert ? 0 : $fpos[$[+2] - 2 * $RecordSize; 851c0b746e5SOllivier Robert ;# anyway as the data may contain "time holes" 852c0b746e5SOllivier Robert ;# our heuristics may baldly fail 853c0b746e5SOllivier Robert ;# so just start at 0 854c0b746e5SOllivier Robert $fpos[$[+2] = 0; 855c0b746e5SOllivier Robert } 856c0b746e5SOllivier Robert } 857c0b746e5SOllivier Robert } 858c0b746e5SOllivier Robert elsif (defined($EndTime)) 859c0b746e5SOllivier Robert { 860c0b746e5SOllivier Robert print "guess starting point according to EndTime ($EndTime)\n" 861c0b746e5SOllivier Robert if $verbose > 3; 862c0b746e5SOllivier Robert 863c0b746e5SOllivier Robert if ($fpos[$[] eq 'end') 864c0b746e5SOllivier Robert { 865c0b746e5SOllivier Robert if (grep($_ eq $fpos[$[+1],@f)) 866c0b746e5SOllivier Robert { 867c0b746e5SOllivier Robert shift(@f) while @f && $f[$[] ne $fpos[$[+1]; 868c0b746e5SOllivier Robert } 869c0b746e5SOllivier Robert else 870c0b746e5SOllivier Robert { 871c0b746e5SOllivier Robert @fpos = ('end', $f[$[], undef); 872c0b746e5SOllivier Robert } 873c0b746e5SOllivier Robert } 874c0b746e5SOllivier Robert else 875c0b746e5SOllivier Robert { 876c0b746e5SOllivier Robert @fpos = ('end', $f[$[], undef); 877c0b746e5SOllivier Robert } 878c0b746e5SOllivier Robert 879c0b746e5SOllivier Robert if (!defined($fpos[$[+2])) 880c0b746e5SOllivier Robert { 881c0b746e5SOllivier Robert local(@x) = reverse(@f); 882c0b746e5SOllivier Robert local($s,$c) = (0,$cnt); 883c0b746e5SOllivier Robert if ($EndTime < $F_last{$x[$[]}) 884c0b746e5SOllivier Robert { 885c0b746e5SOllivier Robert ;# last file will only be used partially 886c0b746e5SOllivier Robert $s = int($F_size{$x[$[]} * 887c0b746e5SOllivier Robert (($EndTime - $F_first{$x[$[]}) / 888c0b746e5SOllivier Robert ($F_last{$x[$[]} - $F_first{$x[$[]}))); 889c0b746e5SOllivier Robert $s = int($s/$RecordSize); 890c0b746e5SOllivier Robert $c -= $s - 1; 891c0b746e5SOllivier Robert if ($c <= 0) 892c0b746e5SOllivier Robert { 893c0b746e5SOllivier Robert ;# start is in the same file 894c0b746e5SOllivier Robert $fpos[$[+1] = $x[$[]; 895c0b746e5SOllivier Robert $fpos[$[+2] = ($c >=-2) ? 0 : (-$c - 2) * $RecordSize; 896c0b746e5SOllivier Robert shift(@f) while @f && ($f[$[] ne $x[$[]); 897c0b746e5SOllivier Robert } 898c0b746e5SOllivier Robert else 899c0b746e5SOllivier Robert { 900c0b746e5SOllivier Robert shift(@x); 901c0b746e5SOllivier Robert } 902c0b746e5SOllivier Robert } 903c0b746e5SOllivier Robert 904c0b746e5SOllivier Robert if (!defined($fpos[$[+2])) 905c0b746e5SOllivier Robert { 906c0b746e5SOllivier Robert local($_); 907c0b746e5SOllivier Robert while($_ = shift(@x)) 908c0b746e5SOllivier Robert { 909c0b746e5SOllivier Robert $s = int($F_size{$_}/$RecordSize); 910c0b746e5SOllivier Robert $c -= $s - 1; 911c0b746e5SOllivier Robert if ($c <= 0) 912c0b746e5SOllivier Robert { 913c0b746e5SOllivier Robert $fpos[$[+1] = $_; 914c0b746e5SOllivier Robert $fpos[$[+2] = ($c>-2) ? 0 : (-$c - 2) * $RecordSize; 915c0b746e5SOllivier Robert shift(@f) while @f && ($f[$[] ne $_); 916c0b746e5SOllivier Robert last; 917c0b746e5SOllivier Robert } 918c0b746e5SOllivier Robert } 919c0b746e5SOllivier Robert } 920c0b746e5SOllivier Robert } 921c0b746e5SOllivier Robert } 922c0b746e5SOllivier Robert else 923c0b746e5SOllivier Robert { 924c0b746e5SOllivier Robert print "guessing starting point according to count ($cnt)\n" 925c0b746e5SOllivier Robert if $verbose > 3; 926c0b746e5SOllivier Robert ;# guess offset to get last available $cnt samples 927c0b746e5SOllivier Robert if ($fpos[$[] eq 'cnt') 928c0b746e5SOllivier Robert { 929c0b746e5SOllivier Robert if (grep($_ eq $fpos[$[+1],@f)) 930c0b746e5SOllivier Robert { 931c0b746e5SOllivier Robert print "old positioning applies\n" if $verbose > 3; 932c0b746e5SOllivier Robert shift(@f) while @f && $f[$[] ne $fpos[$[+1]; 933c0b746e5SOllivier Robert } 934c0b746e5SOllivier Robert else 935c0b746e5SOllivier Robert { 936c0b746e5SOllivier Robert @fpos = ('cnt', $f[$[], undef); 937c0b746e5SOllivier Robert } 938c0b746e5SOllivier Robert } 939c0b746e5SOllivier Robert else 940c0b746e5SOllivier Robert { 941c0b746e5SOllivier Robert @fpos = ('cnt', $f[$[], undef); 942c0b746e5SOllivier Robert } 943c0b746e5SOllivier Robert 944c0b746e5SOllivier Robert if (!defined($fpos[$[+2])) 945c0b746e5SOllivier Robert { 946c0b746e5SOllivier Robert local(@x) = reverse(@f); 947c0b746e5SOllivier Robert local($s,$c) = (0,$cnt); 948c0b746e5SOllivier Robert 949c0b746e5SOllivier Robert local($_); 950c0b746e5SOllivier Robert while($_ = shift(@x)) 951c0b746e5SOllivier Robert { 952c0b746e5SOllivier Robert print "examing \"$_\" $c samples still needed\n" 953c0b746e5SOllivier Robert if $verbose > 4; 954c0b746e5SOllivier Robert $s = int($F_size{$_}/$RecordSize); 955c0b746e5SOllivier Robert $c -= $s - 1; 956c0b746e5SOllivier Robert if ($c <= 0) 957c0b746e5SOllivier Robert { 958c0b746e5SOllivier Robert $fpos[$[+1] = $_; 959c0b746e5SOllivier Robert $fpos[$[+2] = ($c>-2) ? 0 : (-$c - 2) * $RecordSize; 960c0b746e5SOllivier Robert shift(@f) while @f && ($f[$[] ne $_); 961c0b746e5SOllivier Robert last; 962c0b746e5SOllivier Robert } 963c0b746e5SOllivier Robert } 964c0b746e5SOllivier Robert if (!defined($fpos[$[+2])) 965c0b746e5SOllivier Robert { 966c0b746e5SOllivier Robert print "no starting point yet - using start of data\n" 967c0b746e5SOllivier Robert if $verbose > 2; 968c0b746e5SOllivier Robert $fpos[$[+2] = 0; 969c0b746e5SOllivier Robert } 970c0b746e5SOllivier Robert } 971c0b746e5SOllivier Robert } 972c0b746e5SOllivier Robert } 973c0b746e5SOllivier Robert print "Ooops, no suitable input file ??\n" 974c0b746e5SOllivier Robert if $verbose > 1 && @f <= 0; 975c0b746e5SOllivier Robert 976c0b746e5SOllivier Robert printf("Starting at (%s) \"%s\" offset %ld using %d files\n", 977c0b746e5SOllivier Robert $fpos[$[+1], 978c0b746e5SOllivier Robert $F_name{$fpos[$[+1]}, 979c0b746e5SOllivier Robert $fpos[$[+2], 980c0b746e5SOllivier Robert scalar(@f)) 981c0b746e5SOllivier Robert if $verbose > 2; 982c0b746e5SOllivier Robert 983c0b746e5SOllivier Robert $lm = 1; 984c0b746e5SOllivier Robert $l = 0; 985c0b746e5SOllivier Robert foreach $key (@f) 986c0b746e5SOllivier Robert { 987c0b746e5SOllivier Robert $file = $F_name{$key}; 988c0b746e5SOllivier Robert print "processing file \"$file\"\n" if $verbose > 2; 989c0b746e5SOllivier Robert 990c0b746e5SOllivier Robert open(IN,"<$file") || 991c0b746e5SOllivier Robert (warn("$0: cannot read \"$file\": $!\n"), next); 992c0b746e5SOllivier Robert 993c0b746e5SOllivier Robert ;# try to seek to a position nearer to the start of the interesting lines 994c0b746e5SOllivier Robert ;# should always affect only first item in @f 995c0b746e5SOllivier Robert ($key eq $fpos[$[+1]) && 996c0b746e5SOllivier Robert (($verbose > 1) && 997c0b746e5SOllivier Robert print("Seeking to offset $fpos[$[+2]\n"), 998c0b746e5SOllivier Robert seek(IN,$fpos[$[+2],0) || 999c0b746e5SOllivier Robert warn("$0: seek(\"$F_name{$key}\" failed: $|\n")); 1000c0b746e5SOllivier Robert 1001c0b746e5SOllivier Robert while(<IN>) 1002c0b746e5SOllivier Robert { 1003c0b746e5SOllivier Robert $l++; 1004c0b746e5SOllivier Robert ($verbose > 3) && 1005c0b746e5SOllivier Robert (($l % $lm) == 0 && print("\t$l lines read\n") && 1006c0b746e5SOllivier Robert (($l == 2) && ($lm = 10) || 1007c0b746e5SOllivier Robert ($l == 100) && ($lm = 100) || 1008c0b746e5SOllivier Robert ($l == 500) && ($lm = 500) || 1009c0b746e5SOllivier Robert ($l == 1000) && ($lm = 1000) || 1010c0b746e5SOllivier Robert ($l == 5000) && ($lm = 5000) || 1011c0b746e5SOllivier Robert ($l == 10000) && ($lm = 10000))); 1012c0b746e5SOllivier Robert 1013c0b746e5SOllivier Robert @F = split; 1014c0b746e5SOllivier Robert 1015c0b746e5SOllivier Robert next if @F < 6; # no valid input line is this short 1016c0b746e5SOllivier Robert next if $F[$[] eq ""; 1017c0b746e5SOllivier Robert next if ($F[$[] !~ /^\d+$/); 1018c0b746e5SOllivier Robert ($F[$[] !~ /^\d+$/) && # A 'never should have happend' error 1019c0b746e5SOllivier Robert die("$0: unexpected input line: >$_<\n"); 1020c0b746e5SOllivier Robert 1021c0b746e5SOllivier Robert ;# modified Julian to UNIX epoch 1022c0b746e5SOllivier Robert $t = ($F[$[] - $MJD_1970) * 24 * 60 * 60; 1023c0b746e5SOllivier Robert $t += $F[$[+1]; # add seconds + fraction 1024c0b746e5SOllivier Robert 1025c0b746e5SOllivier Robert ;# multiply offset by 1000 to get ms - try to avoid float op 1026c0b746e5SOllivier Robert (($F[$[+2] =~ s/(\d*)\.(\d{3})(\d*)/$1$2.$3/) && 1027c0b746e5SOllivier Robert $F[$[+2] =~ s/0+([\d\.])/($1 eq '.') ? '0.' : $1/e) # strip leading zeros 1028c0b746e5SOllivier Robert || ($F[$[+2] *= 1000); 1029c0b746e5SOllivier Robert 1030c0b746e5SOllivier Robert 1031c0b746e5SOllivier Robert ;# skip samples out of specified time range 1032c0b746e5SOllivier Robert next if (defined($StartTime) && $StartTime > $t); 1033c0b746e5SOllivier Robert next if (defined($EndTime) && $EndTime < $t); 1034c0b746e5SOllivier Robert 1035c0b746e5SOllivier Robert next if defined($lastT) && $t < $lastT; # backward in time ?? 1036c0b746e5SOllivier Robert 1037c0b746e5SOllivier Robert push(@offs,$F[$[+2]); 1038c0b746e5SOllivier Robert push(@freq,$F[$[+3] * (2**20/10**6)); 1039c0b746e5SOllivier Robert push(@cmpl,$F[$[+5]); 1040c0b746e5SOllivier Robert 1041c0b746e5SOllivier Robert push(@break, (defined($lastT) && ($t - $lastT > $deltaT))); 1042c0b746e5SOllivier Robert $lastT = $t; 1043c0b746e5SOllivier Robert push(@time,$t); 1044c0b746e5SOllivier Robert push(@loffset, tell(IN) - length($_)); 1045c0b746e5SOllivier Robert push(@filekey, $key); 1046c0b746e5SOllivier Robert 1047c0b746e5SOllivier Robert shift(@break),shift(@time),shift(@offs), 1048c0b746e5SOllivier Robert shift(@freq), shift(@cmpl),shift(@loffset), 1049c0b746e5SOllivier Robert shift(@filekey) 1050c0b746e5SOllivier Robert if @time > $cnt && 1051c0b746e5SOllivier Robert ! (defined($StartTime) && defined($EndTime)); 1052c0b746e5SOllivier Robert 1053c0b746e5SOllivier Robert last if @time >= $cnt && defined($StartTime) && !defined($EndTime); 1054c0b746e5SOllivier Robert } 1055c0b746e5SOllivier Robert close(IN); 1056c0b746e5SOllivier Robert last if @time >= $cnt && defined($StartTime) && !defined($EndTime); 1057c0b746e5SOllivier Robert } 1058c0b746e5SOllivier Robert print "input scanned ($l lines/",scalar(@time)," samples)\n" 1059c0b746e5SOllivier Robert if $verbose > 1; 1060c0b746e5SOllivier Robert 1061c0b746e5SOllivier Robert if (@time) 1062c0b746e5SOllivier Robert { 1063c0b746e5SOllivier Robert local($_,@F); 1064c0b746e5SOllivier Robert 1065c0b746e5SOllivier Robert local($timebase) unless defined($timebase); 1066c0b746e5SOllivier Robert local($freqbase) unless defined($freqbase); 1067c0b746e5SOllivier Robert local($cmplscale) unless defined($cmplscale); 1068c0b746e5SOllivier Robert 1069c0b746e5SOllivier Robert undef $mintime; 1070c0b746e5SOllivier Robert undef $maxtime; 1071c0b746e5SOllivier Robert undef $minoffs; 1072c0b746e5SOllivier Robert undef $maxoffs; 1073c0b746e5SOllivier Robert undef $minfreq; 1074c0b746e5SOllivier Robert undef $maxfreq; 1075c0b746e5SOllivier Robert undef $mincmpl; 1076c0b746e5SOllivier Robert undef $maxcmpl; 1077c0b746e5SOllivier Robert undef $miny; 1078c0b746e5SOllivier Robert undef $maxy ; 1079c0b746e5SOllivier Robert 1080c0b746e5SOllivier Robert print "computing ranges\n" if $verbose > 2; 1081c0b746e5SOllivier Robert 1082c0b746e5SOllivier Robert $LastCnt = @time; 1083c0b746e5SOllivier Robert 1084c0b746e5SOllivier Robert ;# @time is in ascending order (;-) 1085c0b746e5SOllivier Robert $mintime = $time[$[]; 1086c0b746e5SOllivier Robert $maxtime = $time[$#time]; 1087c0b746e5SOllivier Robert unless (defined($timebase)) 1088c0b746e5SOllivier Robert { 1089c0b746e5SOllivier Robert local($time,@X) = (time); 1090c0b746e5SOllivier Robert @X = localtime($time); 1091c0b746e5SOllivier Robert 1092c0b746e5SOllivier Robert ;# compute today 00:00:00 1093c0b746e5SOllivier Robert $timebase = $time - ((($X[$[+2]*60)+$X[$[+1])*60+$X[$[]); 1094c0b746e5SOllivier Robert 1095c0b746e5SOllivier Robert } 1096c0b746e5SOllivier Robert $LastTimeBase = $timebase; 1097c0b746e5SOllivier Robert 1098c0b746e5SOllivier Robert if ($showoffs) 1099c0b746e5SOllivier Robert { 1100c0b746e5SOllivier Robert local($i,$m,$f); 1101c0b746e5SOllivier Robert 1102c0b746e5SOllivier Robert $minoffs = &min(@offs); 1103c0b746e5SOllivier Robert $maxoffs = &max(@offs); 1104c0b746e5SOllivier Robert 1105c0b746e5SOllivier Robert ;# I know, it is not perl style using indices to access arrays, 1106c0b746e5SOllivier Robert ;# but I have to proccess two arrays in sync, non-destructively 1107c0b746e5SOllivier Robert ;# (otherwise a (shift(@a1),shift(a2)) would do), 1108c0b746e5SOllivier Robert ;# I dont like to make copies of these arrays as they may be huge 1109c0b746e5SOllivier Robert $i = $[; 1110ea906c41SOllivier Robert $lo->sample(($time[$i]-$timebase)/3600,$offs[$i]),$i++ 1111c0b746e5SOllivier Robert while $i <= $#time; 1112c0b746e5SOllivier Robert 1113c0b746e5SOllivier Robert ($minoffs == $maxoffs) && ($minoffs -= 0.1,$maxoffs += 0.1); 1114c0b746e5SOllivier Robert 1115ea906c41SOllivier Robert $i = $lo->sigma(); 1116ea906c41SOllivier Robert $m = $lo->mean(); 1117c0b746e5SOllivier Robert 1118c0b746e5SOllivier Robert print "mean offset: $m sigma: $i\n" if $verbose > 2; 1119c0b746e5SOllivier Robert 1120c0b746e5SOllivier Robert if (($maxoffs - $minoffs) > $MinClip) 1121c0b746e5SOllivier Robert { 1122c0b746e5SOllivier Robert $f = (&abs($minoffs) < &abs($maxoffs)) ? $FuzzLow : $FuzzBig; 1123c0b746e5SOllivier Robert $miny = (($m - $minoffs) <= ($f * $i)) 1124c0b746e5SOllivier Robert ? $minoffs : ($m - $f * $i); 1125c0b746e5SOllivier Robert $f = ($f == $FuzzLow) ? $FuzzBig : $FuzzLow; 1126c0b746e5SOllivier Robert $maxy = (($maxoffs - $m) <= ($f * $i)) 1127c0b746e5SOllivier Robert ? $maxoffs : ($m + $f * $i); 1128c0b746e5SOllivier Robert } 1129c0b746e5SOllivier Robert else 1130c0b746e5SOllivier Robert { 1131c0b746e5SOllivier Robert $miny = $minoffs; 1132c0b746e5SOllivier Robert $maxy = $maxoffs; 1133c0b746e5SOllivier Robert } 1134c0b746e5SOllivier Robert ($maxy-$miny) == 0 && 1135c0b746e5SOllivier Robert (($maxy,$miny) 1136c0b746e5SOllivier Robert = (($maxoffs - $minoffs) > 0) 1137c0b746e5SOllivier Robert ? ($maxoffs,$minoffs) : ($MinClip,-$MinClip)); 1138c0b746e5SOllivier Robert 1139c0b746e5SOllivier Robert $maxy = $MaxY if defined($MaxY) && $MaxY < $maxy; 1140c0b746e5SOllivier Robert $miny = $MinY if defined($MinY) && $MinY > $miny; 1141c0b746e5SOllivier Robert 1142c0b746e5SOllivier Robert print "offset min clipped from $minoffs to $miny\n" 1143c0b746e5SOllivier Robert if $verbose > 2 && $minoffs != $miny; 1144c0b746e5SOllivier Robert print "offset max clipped from $maxoffs to $maxy\n" 1145c0b746e5SOllivier Robert if $verbose > 2 && $maxoffs != $maxy; 1146c0b746e5SOllivier Robert } 1147c0b746e5SOllivier Robert 1148c0b746e5SOllivier Robert if ($showfreq) 1149c0b746e5SOllivier Robert { 1150c0b746e5SOllivier Robert local($i,$m); 1151c0b746e5SOllivier Robert 1152c0b746e5SOllivier Robert $minfreq = &min(@freq); 1153c0b746e5SOllivier Robert $maxfreq = &max(@freq); 1154c0b746e5SOllivier Robert 1155c0b746e5SOllivier Robert $i = $[; 1156ea906c41SOllivier Robert $lf->sample(($time[$i]-$timebase)/3600,$freq[$i]-$minfreq), 1157c0b746e5SOllivier Robert $i++ 1158c0b746e5SOllivier Robert while $i <= $#time; 1159c0b746e5SOllivier Robert 1160ea906c41SOllivier Robert $i = $lf->sigma(); 1161ea906c41SOllivier Robert $m = $lf->mean() + $minfreq; 1162c0b746e5SOllivier Robert 1163c0b746e5SOllivier Robert print "mean frequency: $m sigma: $i\n" if $verbose > 2; 1164c0b746e5SOllivier Robert 1165c0b746e5SOllivier Robert if (defined($maxy)) 1166c0b746e5SOllivier Robert { 1167c0b746e5SOllivier Robert local($s) = 1168c0b746e5SOllivier Robert ($maxfreq - $minfreq) 1169c0b746e5SOllivier Robert ? ($maxy - $miny) / ($maxfreq - $minfreq) : 1; 1170c0b746e5SOllivier Robert 1171c0b746e5SOllivier Robert if (defined($freqbase)) 1172c0b746e5SOllivier Robert { 1173c0b746e5SOllivier Robert $FreqScale = 1; 1174c0b746e5SOllivier Robert $FreqScaleInv = ""; 1175c0b746e5SOllivier Robert } 1176c0b746e5SOllivier Robert else 1177c0b746e5SOllivier Robert { 1178c0b746e5SOllivier Robert $FreqScale = 1; 1179c0b746e5SOllivier Robert $FreqScale = 10 ** int(log($s)/log(10) - 0.9999); 1180c0b746e5SOllivier Robert $FreqScaleInv = 1181c0b746e5SOllivier Robert ("$FreqScale" =~ /^10(0*)$/) ? "0.${1}1" : 1182c0b746e5SOllivier Robert ($FreqScale == 1 ? "" : (1/$FreqScale)); 1183c0b746e5SOllivier Robert 1184c0b746e5SOllivier Robert $freqbase = ($maxfreq + $minfreq)/ 2 * $FreqScale; #$m * $FreqScale; 1185ea906c41SOllivier Robert $freqbase -= ($maxy + $miny) / 2; #$lf->mean(); 1186c0b746e5SOllivier Robert 1187c0b746e5SOllivier Robert ;# round resulting freqbase 1188c0b746e5SOllivier Robert ;# to precision of min max difference 1189c0b746e5SOllivier Robert $s = -12; 1190c0b746e5SOllivier Robert $s = int(log(($maxfreq-$minfreq)*$FreqScale)/log(10))-1 1191c0b746e5SOllivier Robert unless ($maxfreq-$minfreq) < 1e-12; 1192c0b746e5SOllivier Robert $s = 10 ** $s; 1193c0b746e5SOllivier Robert $freqbase = int($freqbase / $s) * $s; 1194c0b746e5SOllivier Robert } 1195c0b746e5SOllivier Robert } 1196c0b746e5SOllivier Robert else 1197c0b746e5SOllivier Robert { 1198c0b746e5SOllivier Robert $FreqScale = 1; 1199c0b746e5SOllivier Robert $FreqScaleInv = ""; 1200c0b746e5SOllivier Robert $freqbase = $m unless defined($freqbase); 1201c0b746e5SOllivier Robert if (($maxfreq - $minfreq) > $MinClip) 1202c0b746e5SOllivier Robert { 1203c0b746e5SOllivier Robert $f = (&abs($minfreq) < &abs($maxfreq)) 1204c0b746e5SOllivier Robert ? $FuzzLow : $FuzzBig; 1205c0b746e5SOllivier Robert $miny = (($freqbase - $minfreq) <= ($f * $i)) 1206c0b746e5SOllivier Robert ? ($minfreq-$freqbase) : (- $f * $i); 1207c0b746e5SOllivier Robert $f = ($f == $FuzzLow) ? $FuzzBig : $FuzzLow; 1208c0b746e5SOllivier Robert $maxy = (($maxfreq - $freqbase) <= ($f * $i)) 1209c0b746e5SOllivier Robert ? ($maxfreq-$freqbase) : ($f * $i); 1210c0b746e5SOllivier Robert } 1211c0b746e5SOllivier Robert else 1212c0b746e5SOllivier Robert { 1213c0b746e5SOllivier Robert $miny = $minfreq - $freqbase; 1214c0b746e5SOllivier Robert $maxy = $maxfreq - $freqbase; 1215c0b746e5SOllivier Robert } 1216c0b746e5SOllivier Robert ($maxy - $miny) == 0 && 1217c0b746e5SOllivier Robert (($maxy,$miny) = 1218c0b746e5SOllivier Robert (($maxfreq - $minfreq) > 0) 1219c0b746e5SOllivier Robert ? ($maxfreq-$freqbase,$minfreq-$freqbase) : (0.5,-0.5)); 1220c0b746e5SOllivier Robert 1221c0b746e5SOllivier Robert $maxy = $MaxY if defined($MaxY) && $MaxY < $maxy; 1222c0b746e5SOllivier Robert $miny = $MinY if defined($MinY) && $MinY > $miny; 1223c0b746e5SOllivier Robert 1224c0b746e5SOllivier Robert print("frequency min clipped from ",$minfreq-$freqbase, 1225c0b746e5SOllivier Robert " to $miny\n") 1226c0b746e5SOllivier Robert if $verbose > 2 && $miny != ($minfreq - $freqbase); 1227c0b746e5SOllivier Robert print("frequency max clipped from ",$maxfreq-$freqbase, 1228c0b746e5SOllivier Robert " to $maxy\n") 1229c0b746e5SOllivier Robert if $verbose > 2 && $maxy != ($maxfreq - $freqbase); 1230c0b746e5SOllivier Robert } 1231c0b746e5SOllivier Robert $LastFreqBaseString = 1232c0b746e5SOllivier Robert sprintf("%g",$freqbase >= 0 ? $freqbase : -$freqbase); 1233c0b746e5SOllivier Robert $LastFreqBase = $freqbase; 1234c0b746e5SOllivier Robert print "LastFreqBaseString now \"$LastFreqBaseString\"\n" 1235c0b746e5SOllivier Robert if $verbose > 5; 1236c0b746e5SOllivier Robert } 1237c0b746e5SOllivier Robert else 1238c0b746e5SOllivier Robert { 1239c0b746e5SOllivier Robert $FreqScale = 1; 1240c0b746e5SOllivier Robert $FreqScaleInv = ""; 1241c0b746e5SOllivier Robert $LastFreqBase = 0; 1242c0b746e5SOllivier Robert $LastFreqBaseString = ""; 1243c0b746e5SOllivier Robert } 1244c0b746e5SOllivier Robert 1245c0b746e5SOllivier Robert if ($showcmpl) 1246c0b746e5SOllivier Robert { 1247c0b746e5SOllivier Robert $mincmpl = &min(@cmpl); 1248c0b746e5SOllivier Robert $maxcmpl = &max(@cmpl); 1249c0b746e5SOllivier Robert 1250c0b746e5SOllivier Robert if (!defined($cmplscale)) 1251c0b746e5SOllivier Robert { 1252c0b746e5SOllivier Robert if (defined($maxy)) 1253c0b746e5SOllivier Robert { 1254c0b746e5SOllivier Robert local($cmp) 1255c0b746e5SOllivier Robert = (&abs($miny) > &abs($maxy)) ? &abs($miny) : $maxy; 1256c0b746e5SOllivier Robert $cmplscale = $cmp == $maxy ? 1 : -1; 1257c0b746e5SOllivier Robert 1258c0b746e5SOllivier Robert foreach (0.01, 0.02, 0.05, 1259c0b746e5SOllivier Robert 0.1, 0.2, 0.25, 0.4, 0.5, 1260c0b746e5SOllivier Robert 1, 2, 4, 5, 1261c0b746e5SOllivier Robert 10, 20, 25, 50, 1262c0b746e5SOllivier Robert 100, 200, 250, 500, 1000) 1263c0b746e5SOllivier Robert { 1264c0b746e5SOllivier Robert $cmplscale *= $_, last if $maxcmpl/$_ <= $cmp; 1265c0b746e5SOllivier Robert } 1266c0b746e5SOllivier Robert } 1267c0b746e5SOllivier Robert else 1268c0b746e5SOllivier Robert { 1269c0b746e5SOllivier Robert $cmplscale = 1; 1270c0b746e5SOllivier Robert $miny = $mincmpl ? 0 : -$MinClip; 1271c0b746e5SOllivier Robert $maxy = $maxcmpl+$MinClip; 1272c0b746e5SOllivier Robert } 1273c0b746e5SOllivier Robert } 1274c0b746e5SOllivier Robert $LastCmplScale = $cmplscale; 1275c0b746e5SOllivier Robert } 1276c0b746e5SOllivier Robert else 1277c0b746e5SOllivier Robert { 1278c0b746e5SOllivier Robert $LastCmplScale = 1; 1279c0b746e5SOllivier Robert } 1280c0b746e5SOllivier Robert 1281c0b746e5SOllivier Robert print "creating plot command input file\n" if $verbose > 2; 1282c0b746e5SOllivier Robert 1283c0b746e5SOllivier Robert 1284c0b746e5SOllivier Robert print OUT ("# preprocessed NTP statistics file for $STATHOST\n"); 1285c0b746e5SOllivier Robert print OUT ("# timebase is: ",&ctime($LastTimeBase)) 1286c0b746e5SOllivier Robert if defined($LastTimeBase); 1287c0b746e5SOllivier Robert print OUT ("# frequency is offset by ", 1288c0b746e5SOllivier Robert ($LastFreqBase >= 0 ? "+" : "-"), 1289c0b746e5SOllivier Robert "$LastFreqBaseString [${FreqScaleInv}ppm]\n"); 1290c0b746e5SOllivier Robert print OUT ("# compliance is scaled by $LastCmplScale\n"); 1291c0b746e5SOllivier Robert print OUT ("# time [h]\toffset [ms]\tfrequency [${FreqScaleInv}ppm]\tcompliance\n"); 1292c0b746e5SOllivier Robert 1293c0b746e5SOllivier Robert printf OUT ("%s%lf\t%lf\t%lf\t%lf\n", 1294c0b746e5SOllivier Robert (shift(@break) ? "\n" : ""), 1295c0b746e5SOllivier Robert (shift(@time) - $LastTimeBase)/3600, 1296c0b746e5SOllivier Robert shift(@offs), 1297c0b746e5SOllivier Robert shift(@freq) * $FreqScale - $LastFreqBase, 1298c0b746e5SOllivier Robert shift(@cmpl) / $LastCmplScale) 1299c0b746e5SOllivier Robert while(@time); 1300c0b746e5SOllivier Robert } 1301c0b746e5SOllivier Robert else 1302c0b746e5SOllivier Robert { 1303c0b746e5SOllivier Robert ;# prevent plotcmd from processing empty file 1304c0b746e5SOllivier Robert print "Creating plot command dummy...\n" if $verbose > 2; 1305c0b746e5SOllivier Robert print OUT "# dummy samples\n0 1 2 3\n1 1 2 3\n"; 1306ea906c41SOllivier Robert $lo->sample(0,1); 1307ea906c41SOllivier Robert $lo->sample(1,1); 1308ea906c41SOllivier Robert $lf->sample(0,2); 1309ea906c41SOllivier Robert $lf->sample(1,2); 1310c0b746e5SOllivier Robert @time = (0, 1); $maxtime = 1; $mintime = 0; 1311c0b746e5SOllivier Robert @offs = (1, 1); $maxoffs = 1; $minoffs = 1; 1312c0b746e5SOllivier Robert @freq = (2, 2); $maxfreq = 2; $minfreq = 2; 1313c0b746e5SOllivier Robert @cmpl = (3, 3); $maxcmpl = 3; $mincmpl = 3; 1314c0b746e5SOllivier Robert $LastCnt = 2; 1315c0b746e5SOllivier Robert $LastFreqBase = 0; 1316c0b746e5SOllivier Robert $LastCmplScale = 1; 1317c0b746e5SOllivier Robert $LastTimeBase = 0; 1318c0b746e5SOllivier Robert $miny = -$MinClip; 1319c0b746e5SOllivier Robert $maxy = 3 + $MinClip; 1320c0b746e5SOllivier Robert } 1321c0b746e5SOllivier Robert close(OUT); 1322c0b746e5SOllivier Robert 1323c0b746e5SOllivier Robert print "plot command input file created\n" 1324c0b746e5SOllivier Robert if $verbose > 2; 1325c0b746e5SOllivier Robert 1326c0b746e5SOllivier Robert 1327c0b746e5SOllivier Robert if (($fpos[$[] eq 'cnt' && scalar(@loffset) >= $cnt) || 1328c0b746e5SOllivier Robert ($fpos[$[] eq 'start' && $mintime <= $StartTime) || 1329c0b746e5SOllivier Robert ($fpos[$[] eq 'end')) 1330c0b746e5SOllivier Robert { 1331c0b746e5SOllivier Robert return ($fpos[$[],$filekey[$[],$loffset[$[]); 1332c0b746e5SOllivier Robert } 1333c0b746e5SOllivier Robert else # found to few lines - next time start search earlier in file 1334c0b746e5SOllivier Robert { 1335c0b746e5SOllivier Robert if ($fpos[$[] eq 'start') 1336c0b746e5SOllivier Robert { 1337c0b746e5SOllivier Robert ;# the timestamps we got for F_first and F_last guaranteed 1338c0b746e5SOllivier Robert ;# that no file is left out 1339c0b746e5SOllivier Robert ;# the only thing that could happen is: 1340c0b746e5SOllivier Robert ;# we guessed the starting point wrong 1341c0b746e5SOllivier Robert ;# compute a new guess from the first record found 1342c0b746e5SOllivier Robert ;# if this equals our last guess use data of first record 1343c0b746e5SOllivier Robert ;# otherwise try new guess 1344c0b746e5SOllivier Robert 1345c0b746e5SOllivier Robert if ($fpos[$[+1] eq $filekey[$[] && $loffset[$[] > $fpos[$[+2]) 1346c0b746e5SOllivier Robert { 1347c0b746e5SOllivier Robert local($noff); 1348c0b746e5SOllivier Robert $noff = $loffset[$[] - ($cnt - @loffset + 1) * $RecordSize; 1349c0b746e5SOllivier Robert $noff = 0 if $noff < 0; 1350c0b746e5SOllivier Robert 1351c0b746e5SOllivier Robert return (@fpos[$[,$[+1], ($noff == $fpos[$[+2]) ? $loffset[$[] : $noff); 1352c0b746e5SOllivier Robert } 1353c0b746e5SOllivier Robert return ($fpos[$[],$filekey[$[],$loffset[$[]); 1354c0b746e5SOllivier Robert } 1355c0b746e5SOllivier Robert elsif ($fpos[$[] eq 'end' || $fpos[$[] eq 'cnt') 1356c0b746e5SOllivier Robert { 1357c0b746e5SOllivier Robert ;# try to start earlier in file 1358c0b746e5SOllivier Robert ;# if we already started at the beginning 1359c0b746e5SOllivier Robert ;# try to use previous file 1360c0b746e5SOllivier Robert ;# this assumes distance to better starting point is at most one file 1361c0b746e5SOllivier Robert ;# the primary guess at top of genfile() should usually allow this 1362c0b746e5SOllivier Robert ;# assumption 1363c0b746e5SOllivier Robert ;# if the offset of the first sample used is within 1364c0b746e5SOllivier Robert ;# a different file than we guessed it must have occurred later 1365c0b746e5SOllivier Robert ;# in the sequence of files 1366c0b746e5SOllivier Robert ;# this only can happen if our starting file did not contain 1367c0b746e5SOllivier Robert ;# a valid sample from the starting point we guessed 1368c0b746e5SOllivier Robert ;# however this does not invalidate our assumption, no check needed 1369c0b746e5SOllivier Robert local($noff,$key); 1370c0b746e5SOllivier Robert if ($fpos[$[+2] > 0) 1371c0b746e5SOllivier Robert { 1372c0b746e5SOllivier Robert $noff = $fpos[$[+2] - $RecordSize * ($cnt - @loffset + 1); 1373c0b746e5SOllivier Robert $noff = 0 if $noff < 0; 1374c0b746e5SOllivier Robert return (@fpos[$[,$[+1],$noff); 1375c0b746e5SOllivier Robert } 1376c0b746e5SOllivier Robert else 1377c0b746e5SOllivier Robert { 1378c0b746e5SOllivier Robert if ($fpos[$[+1] eq $F_files[$[]) 1379c0b746e5SOllivier Robert { 1380c0b746e5SOllivier Robert ;# first file - and not enough samples 1381c0b746e5SOllivier Robert ;# use data of first sample 1382c0b746e5SOllivier Robert return ($fpos[$[], $filekey[$[], $loffset[$[]); 1383c0b746e5SOllivier Robert } 1384c0b746e5SOllivier Robert else 1385c0b746e5SOllivier Robert { 1386c0b746e5SOllivier Robert ;# search key of previous file 1387c0b746e5SOllivier Robert $key = $F_files[$[]; 1388c0b746e5SOllivier Robert @F = reverse(@F_files); 1389c0b746e5SOllivier Robert while ($_ = shift(@F)) 1390c0b746e5SOllivier Robert { 1391c0b746e5SOllivier Robert if ($_ eq $fpos[$[+1]) 1392c0b746e5SOllivier Robert { 1393c0b746e5SOllivier Robert $key = shift(@F) if @F; 1394c0b746e5SOllivier Robert last; 1395c0b746e5SOllivier Robert } 1396c0b746e5SOllivier Robert } 1397c0b746e5SOllivier Robert $noff = int($F_size{$key} / $RecordSize); 1398c0b746e5SOllivier Robert $noff -= $cnt - @loffset; 1399c0b746e5SOllivier Robert $noff = 0 if $noff < 0; 1400c0b746e5SOllivier Robert $noff *= $RecordSize; 1401c0b746e5SOllivier Robert return ($fpos[$[], $key, $noff); 1402c0b746e5SOllivier Robert } 1403c0b746e5SOllivier Robert } 1404c0b746e5SOllivier Robert } 1405c0b746e5SOllivier Robert else 1406c0b746e5SOllivier Robert { 1407c0b746e5SOllivier Robert return (); 1408c0b746e5SOllivier Robert } 1409c0b746e5SOllivier Robert 1410c0b746e5SOllivier Robert return 0 if @loffset <= 1 || ($loffset[$#loffset] - $loffset[$[]) <= 1; 1411c0b746e5SOllivier Robert 1412c0b746e5SOllivier Robert ;# EOF - 1.1 * avg(line) * $cnt 1413c0b746e5SOllivier Robert local($val) = $loffset[$#loffset] 1414c0b746e5SOllivier Robert - $cnt * 11 * (($loffset[$#loffset] - $loffset[$[]) / @loffset) / 10; 1415c0b746e5SOllivier Robert return ($val < 0) ? 0 : $val; 1416c0b746e5SOllivier Robert } 1417c0b746e5SOllivier Robert} 1418c0b746e5SOllivier Robert 1419c0b746e5SOllivier Robert$Ltime = -1 if ! defined($Ltime); 1420c0b746e5SOllivier Robert$LastFreqBase = 0; 1421c0b746e5SOllivier Robert$LastFreqBaseString = "??"; 1422c0b746e5SOllivier Robert 1423c0b746e5SOllivier Robert;# initial setup of plot 1424c0b746e5SOllivier Robertprint "initialize plotting\n" if $verbose; 1425c0b746e5SOllivier Robertif (defined($PrintIt)) 1426c0b746e5SOllivier Robert{ 1427c0b746e5SOllivier Robert if ($PrintIt =~ m,/,) 1428c0b746e5SOllivier Robert { 1429c0b746e5SOllivier Robert print "Saving plot to file $PrintIt\n"; 1430c0b746e5SOllivier Robert print PLOT "set output '$PrintIt'\n"; 1431c0b746e5SOllivier Robert } 1432c0b746e5SOllivier Robert else 1433c0b746e5SOllivier Robert { 1434c0b746e5SOllivier Robert print "Printing plot on printer $PrintIt\n"; 1435c0b746e5SOllivier Robert print PLOT "set output '| lpr -P$PrintIt -h'\n"; 1436c0b746e5SOllivier Robert } 1437c0b746e5SOllivier Robert print PLOT "set terminal postscript landscape color solid 'Helvetica' 10\n"; 1438c0b746e5SOllivier Robert} 1439c0b746e5SOllivier Robertprint PLOT "set grid\n"; 1440c0b746e5SOllivier Robertprint PLOT "set tics out\n"; 1441c0b746e5SOllivier Robertprint PLOT "set format y '%g '\n"; 1442c0b746e5SOllivier Robertprintf PLOT "set time 47\n" unless defined($PrintIt); 1443c0b746e5SOllivier Robert 1444c0b746e5SOllivier Robert@filepos =(); 1445c0b746e5SOllivier Robertwhile(1) 1446c0b746e5SOllivier Robert{ 1447c0b746e5SOllivier Robert print &ctime(time) if $verbose; 1448c0b746e5SOllivier Robert 1449c0b746e5SOllivier Robert ;# update diplay characteristics 1450c0b746e5SOllivier Robert &read_config;# unless defined($PrintIt); 1451c0b746e5SOllivier Robert 1452c0b746e5SOllivier Robert unlink($tmpfile); 1453ea906c41SOllivier Robert my $lo = lr->new(); 1454ea906c41SOllivier Robert my $lf = lr->new(); 1455ea906c41SOllivier Robert 1456ea906c41SOllivier Robert @filepos = &genfile($samples,$srcprefix,$tmpfile,$lo,$lf,@filepos); 1457c0b746e5SOllivier Robert 1458c0b746e5SOllivier Robert ;# make plotcmd display samples 1459ea906c41SOllivier Robert make_doplot($lo, $lf); 1460c0b746e5SOllivier Robert print "Displaying plot...\n" if $verbose > 1; 1461c0b746e5SOllivier Robert print "command for plot sub process:\n$doplot----\n" if $verbose > 3; 1462c0b746e5SOllivier Robert print PLOT $doplot; 1463c0b746e5SOllivier Robert} 1464c0b746e5SOllivier Robertcontinue 1465c0b746e5SOllivier Robert{ 1466c0b746e5SOllivier Robert if (defined($PrintIt)) 1467c0b746e5SOllivier Robert { 1468c0b746e5SOllivier Robert delete $SIG{'CHLD'}; 1469c0b746e5SOllivier Robert print PLOT "quit\n"; 1470c0b746e5SOllivier Robert close(PLOT); 1471c0b746e5SOllivier Robert if ($PrintIt =~ m,/,) 1472c0b746e5SOllivier Robert { 1473c0b746e5SOllivier Robert print "Plot saved to file $PrintIt\n"; 1474c0b746e5SOllivier Robert } 1475c0b746e5SOllivier Robert else 1476c0b746e5SOllivier Robert { 1477c0b746e5SOllivier Robert print "Plot spooled to printer $PrintIt\n"; 1478c0b746e5SOllivier Robert } 1479c0b746e5SOllivier Robert unlink($tmpfile); 1480c0b746e5SOllivier Robert exit(0); 1481c0b746e5SOllivier Robert } 1482c0b746e5SOllivier Robert ;# wait $delay seconds 1483c0b746e5SOllivier Robert print "waiting $delay seconds ..." if $verbose > 2; 1484c0b746e5SOllivier Robert sleep($delay); 1485c0b746e5SOllivier Robert print " continuing\n" if $verbose > 2; 1486c0b746e5SOllivier Robert undef($LastFreqBaseString); 1487c0b746e5SOllivier Robert} 1488c0b746e5SOllivier Robert 1489c0b746e5SOllivier Robert 1490c0b746e5SOllivier Robertsub date_time_spec2seconds 1491c0b746e5SOllivier Robert{ 1492c0b746e5SOllivier Robert local($_) = @_; 1493c0b746e5SOllivier Robert ;# a date_time_spec consistes of: 1494c0b746e5SOllivier Robert ;# YYYY-MM-DD_HH:MM:SS.ms 1495c0b746e5SOllivier Robert ;# values can be omitted from the beginning and default than to 1496c0b746e5SOllivier Robert ;# values of current date 1497c0b746e5SOllivier Robert ;# values omitted from the end default to lowest possible values 1498c0b746e5SOllivier Robert 1499c0b746e5SOllivier Robert local($time) = time; 1500c0b746e5SOllivier Robert local($sec,$min,$hour,$mday,$mon,$year) 1501c0b746e5SOllivier Robert = localtime($time); 1502c0b746e5SOllivier Robert 1503c0b746e5SOllivier Robert local($last) = (); 1504c0b746e5SOllivier Robert 1505c0b746e5SOllivier Robert s/^\D*(.*\d)\D*/$1/; # strip off garbage 1506c0b746e5SOllivier Robert 1507c0b746e5SOllivier Robert PARSE: 1508c0b746e5SOllivier Robert { 1509c0b746e5SOllivier Robert if (s/^(\d{4})(-|$)//) 1510c0b746e5SOllivier Robert { 1511c0b746e5SOllivier Robert if ($1 < 1970) 1512c0b746e5SOllivier Robert { 1513c0b746e5SOllivier Robert warn("$0: can not handle years before 1970 - year $1 ignored\n"); 1514c0b746e5SOllivier Robert return undef; 1515c0b746e5SOllivier Robert } 1516c0b746e5SOllivier Robert elsif ( $1 >= 2070) 1517c0b746e5SOllivier Robert { 1518c0b746e5SOllivier Robert warn("$0: can not handle years past 2070 - year $1 ignored\n"); 1519c0b746e5SOllivier Robert return undef; 1520c0b746e5SOllivier Robert } 1521c0b746e5SOllivier Robert else 1522c0b746e5SOllivier Robert { 1523c0b746e5SOllivier Robert $year = $1 % 100; # 0<= $year < 100 1524c0b746e5SOllivier Robert ;# - interpreted 70 .. 99,00 .. 69 1525c0b746e5SOllivier Robert } 1526c0b746e5SOllivier Robert $last = $[ + 5; 1527c0b746e5SOllivier Robert last PARSE if $_ eq ''; 1528c0b746e5SOllivier Robert warn("$0: bad date_time_spec: \"$_\" found after YEAR\n"), 1529c0b746e5SOllivier Robert return(undef) 1530c0b746e5SOllivier Robert if $2 eq ''; 1531c0b746e5SOllivier Robert } 1532c0b746e5SOllivier Robert 1533c0b746e5SOllivier Robert if (s/^(\d{1,2})(-|$)//) 1534c0b746e5SOllivier Robert { 1535c0b746e5SOllivier Robert warn("$0: implausible month $1\n"),return(undef) 1536c0b746e5SOllivier Robert if $1 < 1 || $1 > 12; 1537c0b746e5SOllivier Robert $mon = $1 - 1; 1538c0b746e5SOllivier Robert $last = $[ + 4; 1539c0b746e5SOllivier Robert last PARSE if $_ eq ''; 1540c0b746e5SOllivier Robert warn("$0: bad date_time_spec: \"$_\" found after MONTH\n"), 1541c0b746e5SOllivier Robert return(undef) 1542c0b746e5SOllivier Robert if $2 eq ''; 1543c0b746e5SOllivier Robert } 1544c0b746e5SOllivier Robert else 1545c0b746e5SOllivier Robert { 1546c0b746e5SOllivier Robert warn("$0: bad date_time_spec \"$_\"\n"),return(undef) 1547c0b746e5SOllivier Robert if defined($last); 1548c0b746e5SOllivier Robert 1549c0b746e5SOllivier Robert } 1550c0b746e5SOllivier Robert 1551c0b746e5SOllivier Robert if (s/^(\d{1,2})([_ ]|$)//) 1552c0b746e5SOllivier Robert { 1553c0b746e5SOllivier Robert warn("$0: implausible month day $1 for month ".($mon+1)." (". 1554c0b746e5SOllivier Robert $MaxNumDaysPerMonth[$mon].")$mon\n"), 1555c0b746e5SOllivier Robert return(undef) 1556c0b746e5SOllivier Robert if $1 < 1 || $1 > $MaxNumDaysPerMonth[$mon]; 1557c0b746e5SOllivier Robert $mday = $1; 1558c0b746e5SOllivier Robert $last = $[ + 3; 1559c0b746e5SOllivier Robert last PARSE if $_ eq ''; 1560c0b746e5SOllivier Robert warn("$0: bad date_time_spec \"$_\" found after MDAY\n"), 1561c0b746e5SOllivier Robert return(undef) 1562c0b746e5SOllivier Robert if $2 eq ''; 1563c0b746e5SOllivier Robert } 1564c0b746e5SOllivier Robert else 1565c0b746e5SOllivier Robert { 1566c0b746e5SOllivier Robert warn("$0: bad date_time_spec \"$_\"\n"), return undef 1567c0b746e5SOllivier Robert if defined($last); 1568c0b746e5SOllivier Robert } 1569c0b746e5SOllivier Robert 1570c0b746e5SOllivier Robert ;# now we face a problem: 1571c0b746e5SOllivier Robert ;# if ! defined($last) a prefix of "07:" 1572c0b746e5SOllivier Robert ;# can be either 07:MM or 07:ss 1573c0b746e5SOllivier Robert ;# to get the second interpretation make the user add 1574c0b746e5SOllivier Robert ;# a msec fraction part and check for this special case 1575c0b746e5SOllivier Robert if (! defined($last) && s/^(\d{1,2}):(\d{1,2}\.\d+)//) 1576c0b746e5SOllivier Robert { 1577c0b746e5SOllivier Robert warn("$0: implausible minute $1\n"), return undef 1578c0b746e5SOllivier Robert if $1 < 0 || $1 >= 60; 1579c0b746e5SOllivier Robert warn("$0: implausible second $1\n"), return undef 1580c0b746e5SOllivier Robert if $2 < 0 || $2 >= 60; 1581c0b746e5SOllivier Robert $min = $1; 1582c0b746e5SOllivier Robert $sec = $2; 1583c0b746e5SOllivier Robert $last = $[ + 1; 1584c0b746e5SOllivier Robert last PARSE if $_ eq ''; 1585c0b746e5SOllivier Robert warn("$0: bad date_time_spec \"$_\" after SECONDS\n"); 1586c0b746e5SOllivier Robert return undef; 1587c0b746e5SOllivier Robert } 1588c0b746e5SOllivier Robert 1589c0b746e5SOllivier Robert if (s/^(\d{1,2})(:|$)//) 1590c0b746e5SOllivier Robert { 1591c0b746e5SOllivier Robert warn("$0: implausible hour $1\n"), return undef 1592c0b746e5SOllivier Robert if $1 < 0 || $1 > 24; 1593c0b746e5SOllivier Robert $hour = $1; 1594c0b746e5SOllivier Robert $last = $[ + 2; 1595c0b746e5SOllivier Robert last PARSE if $_ eq ''; 1596c0b746e5SOllivier Robert warn("$0: bad date_time_spec found \"$_\" after HOUR\n"), 1597c0b746e5SOllivier Robert return undef 1598c0b746e5SOllivier Robert if $2 eq ''; 1599c0b746e5SOllivier Robert } 1600c0b746e5SOllivier Robert else 1601c0b746e5SOllivier Robert { 1602c0b746e5SOllivier Robert warn("$0: bad date_time_spec \"$_\"\n"), return undef 1603c0b746e5SOllivier Robert if defined($last); 1604c0b746e5SOllivier Robert } 1605c0b746e5SOllivier Robert 1606c0b746e5SOllivier Robert if (s/^(\d{1,2})(:|$)//) 1607c0b746e5SOllivier Robert { 1608c0b746e5SOllivier Robert warn("$0: implausible minute $1\n"), return undef 1609c0b746e5SOllivier Robert if $1 < 0 || $1 >=60; 1610c0b746e5SOllivier Robert $min = $1; 1611c0b746e5SOllivier Robert $last = $[ + 1; 1612c0b746e5SOllivier Robert last PARSE if $_ eq ''; 1613c0b746e5SOllivier Robert warn("$0: bad date_time_spec found \"$_\" after MINUTE\n"), 1614c0b746e5SOllivier Robert return undef 1615c0b746e5SOllivier Robert if $2 eq ''; 1616c0b746e5SOllivier Robert } 1617c0b746e5SOllivier Robert else 1618c0b746e5SOllivier Robert { 1619c0b746e5SOllivier Robert warn("$0: bad date_time_spec \"$_\"\n"), return undef 1620c0b746e5SOllivier Robert if defined($last); 1621c0b746e5SOllivier Robert } 1622c0b746e5SOllivier Robert 1623c0b746e5SOllivier Robert if (s/^(\d{1,2}(\.\d+)?)//) 1624c0b746e5SOllivier Robert { 1625c0b746e5SOllivier Robert warn("$0: implausible second $1\n"), return undef 1626c0b746e5SOllivier Robert if $1 < 0 || $1 >=60; 1627c0b746e5SOllivier Robert $sec = $1; 1628c0b746e5SOllivier Robert $last = $[; 1629c0b746e5SOllivier Robert last PARSE if $_ eq ''; 1630c0b746e5SOllivier Robert warn("$0: bad date_time_spec found \"$_\" after SECOND\n"); 1631c0b746e5SOllivier Robert return undef; 1632c0b746e5SOllivier Robert } 1633c0b746e5SOllivier Robert } 1634c0b746e5SOllivier Robert 1635c0b746e5SOllivier Robert return $time unless defined($last); 1636c0b746e5SOllivier Robert 1637c0b746e5SOllivier Robert $sec = 0 if $last > $[; 1638c0b746e5SOllivier Robert $min = 0 if $last > $[ + 1; 1639c0b746e5SOllivier Robert $hour = 0 if $last > $[ + 2; 1640c0b746e5SOllivier Robert $mday = 1 if $last > $[ + 3; 1641c0b746e5SOllivier Robert $mon = 0 if $last > $[ + 4; 1642c0b746e5SOllivier Robert local($rtime) = &timelocal($sec,$min,$hour,$mday,$mon,$year, 0,0, 0); 1643c0b746e5SOllivier Robert 1644c0b746e5SOllivier Robert ;# $rtime may be off if daylight savings time is in effect at given date 1645c0b746e5SOllivier Robert return $rtime + ($sec - int($sec)) 1646c0b746e5SOllivier Robert if $hour == (localtime($rtime))[$[+2]; 1647c0b746e5SOllivier Robert return 1648c0b746e5SOllivier Robert &timelocal($sec,$min,$hour,$mday,$mon,$year, 0,0, 1) 1649c0b746e5SOllivier Robert + ($sec - int($sec)); 1650c0b746e5SOllivier Robert} 1651c0b746e5SOllivier Robert 1652c0b746e5SOllivier Robert 1653c0b746e5SOllivier Robertsub min 1654c0b746e5SOllivier Robert{ 1655c0b746e5SOllivier Robert local($m) = shift; 1656c0b746e5SOllivier Robert 1657c0b746e5SOllivier Robert grep((($m > $_) && ($m = $_),0),@_); 1658c0b746e5SOllivier Robert $m; 1659c0b746e5SOllivier Robert} 1660c0b746e5SOllivier Robert 1661c0b746e5SOllivier Robertsub max 1662c0b746e5SOllivier Robert{ 1663c0b746e5SOllivier Robert local($m) = shift; 1664c0b746e5SOllivier Robert 1665c0b746e5SOllivier Robert grep((($m < $_) && ($m = $_),0),@_); 1666c0b746e5SOllivier Robert $m; 1667c0b746e5SOllivier Robert} 1668