-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathreadS
executable file
·183 lines (160 loc) · 5.56 KB
/
readS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
#!/usr/bin/perl -w
# Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
#
# readS may be copied only under the terms of either the Artistic License
# or the GNU General Public License, which may be found in the source kit
use Switch;
use Getopt::Std;
my $Version= '1.0';
my $Copyright='Copyright 2008 Hewlett-Packard Development Company, L.P.';
my $License= "readS may be copied only under the terms of either the Artistic License\n";
$License.= "or the GNU General Public License, which may be found in the source kit";
# just to handle debugging switcjh, noting we have to have 2nd
# instances of '$opt_d', '$opt_h', 'opt_t' and $opt_v to get rid of -w warning.
getopts('dhp:tv');
help($Copyright, $License) if defined($opt_h);
error("readS V$Version\n$Copyright\n$License") if defined($opt_v);
my $debug= defined($opt_d) ? 1 : 0;
my $precision=defined($opt_p) ? $opt_p : 0;
my $timeFlag= defined($opt_t) ? 1 : 0;
$opt_d=$opt_h=$opt_t=$opt_v='';
use strict;
# We need a minimum of 2 args
error("V$Version usage: readS dir expr0 [oper1 expr1 [oper2 expr2...]]")
if !defined($ARGV[1]);
# parse first argument, directory where S file should be written by Collectl
my $directory=shift;
error("$directory/S doesn't exist, aborting...") if !-e "$directory/S";
# read S file and store lines into the 'lines' array
open S, "<$directory/S" or error("Couldn't open '$directory/S'");
my @lines=<S>;
close S;
my $time='';
if ($timeFlag)
{
# Since we know the time is in the first line, this is faster than
# calling getValue() to do the work.
$lines[0]=~/time (\S+?)\)/;
$time="$1 ";
}
# concatenate all remaining args into one long string starting with '+'
# such that we have groups of <operator><obect> followed by a trailing
# '+' to make the pattern matching work
my $catvar='+';
foreach my $arg (@ARGV)
{
$catvar.="$arg ";
}
$catvar=~s/ $/+/;
my $result=0;
while ($catvar ne '+')
{
# Format of the form: 'sign expression sign...' where whitespace optional
print "Processing: $catvar\n" if $debug;
$catvar=~/\s*([+\-X\/])\s*(.+?)\s*([+\-X\/].*)/;
my $oper=$1;
my $expr=$2;
$catvar=$3;
# Let's look at the expression and it's either numeric OR something in the
# s-expression. Since the regx will pass '.' as a numeric we need to see
# if one slipped through and so treat as an s-expr to be caught in getValue()
my $value=($expr!~/^[-\+]?\d*?[.]?\d*$/ || $expr eq '.') ? getValue($expr) : $expr;
print " Oper: $oper Expr: $expr Leftover: $catvar\n" if $debug;
# take appropriate action, aborting when unkown operator
switch ($oper)
{
case '+' { $result+=$value; }
case '-' { $result-=$value; }
case 'X' { $result*=$value; }
case '/' { $result/=$value; }
else { error("Unkown operator '$oper', aborting..."); }
}
print " Value: $value Subtotal: $result\n" if $debug;
}
# output result, with appropriate floating point format
printf "$time%.${precision}f\n", $result;
# retrieve metric from content of S files previously put into the
# 'lines' array, according to single category.variable argument
# passed to this subroutine
sub getValue
{
# retrieve category and variable from argument
my $catvar=shift;
my ($category, $variable, $instance)=split(/\./, $catvar);
error("Could not split '$catvar' in category.variable[.instance], aborting...") if !defined($variable);
# find numerical value in content of 'S' file
if (!defined($instance))
{
# reading a summary, of the form category.variable
foreach my $line (@lines)
{
return $1 if $line=~/^\($category .*$variable (\d+)/;
}
error("Could not find variable '$variable' in category '$category', aborting...");
}
else
{
# reading a detailed value, of the form category.variable.instance; tricky...
my $pass=0;
my $instNum=0;
foreach my $line (@lines)
{
if ($pass==0 && $line=~/^\($category/)
{
$pass=1;
}
# pass #1: look for a line where instances are listed (contains 'name')
if ($pass==1 && $line=~/\(name/)
{
foreach my $inst (split /\s+/, $line)
{
$inst=~s/[()]//g; # strip leading and trailing '()' if any
if ($instNum>1 && $instance=~/$inst/)
{
$pass=2; # instance number found in 'name' entry
last;
}
$instNum++;
}
}
# pass #2: read now $instNum-th numerical value
if ($pass==2 && $line=~/\($variable/)
{
my @array=split(/\s+/, $line);
$array[$instNum]=~s/[()]//g; # strip leading and trailing '()' if any
return $array[$instNum];
}
}
error("Could not find instance '$instance' of variable '$variable' in category '$category', aborting...");
}
}
sub help
{
my $copyright=shift;
my $license=shift;
my $help=<<EOF;
CMUreadS [-d] [-p prec] [-h] [-t] dir expr0 [oper1 expr1 [oper2 expr2...]
-d enables debugging/expression evaluation tracing
-h print this text
-p prec precision of result, default=0
-t preface output with UTC time
dir directory connating s-expression file 'S'
expr expression to evaluate, either a numerical constant OR
category1.variable1[.instance1] which names the category
on the data, one of multiple variables of that category
and if detail data, the instance name
Examples
readS /var/log/collectl ctxint.ctx
readS -p2 /var/log/collectl ctxint.ctx/1024
readS -p2 /var/log/collectl cpuinfo.cpu0.user+cpuinfo.cpu0.nice
EOF
print $help;
print "\n$copyright\n$license\n";
exit;
}
# print error message, passed as single argument
sub error
{
print "$_[0]\n";
exit;
}