File Coverage

blib/lib/Lustre/Info.pm
Criterion Covered Total %
statement 37 129 28.6
branch 4 54 7.4
condition 0 3 0.0
subroutine 14 24 58.3
pod 11 12 91.6
total 66 222 29.7


line stmt bran cond sub pod time code
1             #
2             # Lutre::Info Mainclass
3             #
4             # (C) 2010 Adrian Ulrich -
5             #
6             # This program is free software; you can redistribute it and/or
7             # modify it under the same terms as Perl itself.
8             #
9              
10             package Lustre::Info;
11              
12 1     1   788 use strict;
  1         1  
  1         32  
13 1     1   5 use warnings;
  1         1  
  1         30  
14 1     1   663 use Lustre::Info::OST;
  1         1  
  1         24  
15 1     1   446 use Lustre::Info::Export;
  1         2  
  1         24  
16 1     1   608 use Lustre::Info::MDT;
  1         3  
  1         31  
17              
18             require Exporter;
19 1     1   4 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         2  
  1         5278  
20              
21             @ISA = qw(Exporter);
22             @EXPORT = qw();
23             @EXPORT_OK = qw();
24             $VERSION = '0.02';
25              
26 1     1   7 use constant PROCFS_LUSTRE => "/proc/fs/lustre";
  1         188  
  1         603  
27 1     1   6 use constant PROCFS_OBDFILTER => "/proc/fs/lustre/obdfilter";
  1         1  
  1         53  
28 1     1   5 use constant PROCFS_MDS => "/proc/fs/lustre/mds";
  1         2  
  1         5382  
29              
30             ##########################################################################
31             # Creates a new Spy Object
32             sub new {
33 1     1 1 920 my($class,%args) = @_;
34 1         4 my $self = {};
35 1         5 bless($self,$class);
36 1         5 return $self;
37             }
38              
39             ##########################################################################
40             # Return (uncached) list of all OBD Objects
41             sub get_ost_list {
42 1     1 1 452 my($self) = @_;
43 1         2 my @list = ();
44 1 50       41 opendir(OBD, PROCFS_OBDFILTER) or return \@list;
45 0         0 while(defined(my $dirent = readdir(OBD))) {
46 0 0       0 next if $dirent =~ /^\./; # dotfile
47 0 0       0 next if ! -d join("/",PROCFS_OBDFILTER, $dirent);
48 0         0 push(@list, $dirent);
49             }
50 0         0 closedir(OBD);
51 0         0 return \@list;
52             }
53              
54             ##########################################################################
55             # Returns (uncached) list of all exports known to all OSTs
56             sub get_export_list {
57 0     0 1 0 my($self) = @_;
58 0         0 my $list = {};
59 0         0 my @osts = $self->get_ost_list;
60            
61 0         0 foreach my $this_ost (@{$self->get_ost_list}) {
  0         0  
62 0         0 my $export_dir = PROCFS_OBDFILTER."/$this_ost/exports/";
63 0 0       0 opendir(EXP, $export_dir) or next;
64 0         0 while(defined(my $dirent = readdir(EXP))) {
65 0 0       0 next if $dirent =~ /^\./; # dotfile;
66 0 0       0 next if ! -d $export_dir.$dirent;
67 0         0 $list->{$dirent}++;
68             }
69 0         0 closedir(EXP);
70             }
71 0         0 my @exports = keys(%$list);
72 0         0 return \@exports;
73             }
74              
75             ##########################################################################
76             # Return (unchaced) list of all MTD Objects
77             sub get_mdt_list {
78 0     0 1 0 my @list = ();
79 0 0       0 opendir(OBD, PROCFS_MDS) or return \@list;
80 0         0 while(defined(my $dirent = readdir(OBD))) {
81 0 0       0 next if $dirent =~ /^\./; # dotfile
82 0 0       0 next if ! -d join("/",PROCFS_MDS, $dirent);
83 0         0 push(@list, $dirent);
84             }
85 0         0 closedir(OBD);
86 0         0 return \@list;
87             }
88              
89             ##########################################################################
90             # Returns TRUE if current host is acting as an OST
91             sub is_ost {
92 1 50   1 1 55 return ( -d PROCFS_LUSTRE."/ost" ? 1 : 0 );
93             }
94              
95             ##########################################################################
96             # Returns TRUE if current host is acting as an MDS
97             sub is_mds {
98 1 50   1 1 529 return ( -d PROCFS_LUSTRE."/mds" ? 1 : 0 );
99             }
100              
101             ##########################################################################
102             # Returns TRUE if current host is acting as an MDT
103             sub is_mdt {
104 1 50   1 1 506 return ( -d PROCFS_LUSTRE."/mdt" ? 1 : 0 );
105             }
106              
107             ##########################################################################
108             # Return object to __PACKAGE__::OST Class
109             sub get_ost {
110 0     0 1   my($self,$ostname) = @_;
111 0           return Lustre::Info::OST->new(super=>$self, ostname=>$ostname);
112             }
113              
114             ##########################################################################
115             # Returns object to __PACKAGE__::Export Class
116             sub get_export {
117 0     0 1   my($self, $expname) = @_;
118 0           return Lustre::Info::Export->new(super=>$self, export=>$expname);
119             }
120              
121             ##########################################################################
122             # Returns object to __PACKAGE__::MDT
123             sub get_mdt {
124 0     0 1   my($self, $mdtname) = @_;
125 0           return Lustre::Info::MDT->new(super=>$self, mdtname=>$mdtname);
126             }
127              
128             ##########################################################################
129             # Return current lustre version (undef if lustre is not loaded)
130             sub get_lustre_version {
131 0     0 1   my $ver = undef;
132 0 0         open(LF, PROCFS_LUSTRE."/version") or return $ver;
133 0           while() {
134 0 0         if($_ =~ /^lustre: (\d.+)$/) { $ver = $1 }
  0            
135             }
136 0           close(LF);
137 0           return $ver;
138             }
139              
140              
141              
142              
143             ##########################################################################
144             # Try to parse a lustre statistics file created by lprocfs
145             sub _parse_stats_file {
146 0     0     my($self,$fname) = @_;
147            
148 0           my $data = {};
149 0           my $snap = 0;
150 0 0         open(P, $fname) or return undef;
151 0           while(

) {

152             # req_waittime 21932809 samples [usec] 3 1047811 9446315012 4121280741355958 (<-- sqcount)
153 0 0         if(my($name,$samples,$format,$min,$max,$count) = $_ =~ /^(\S+)\s+(\d+) samples \[(.+)\]\s+(\d+)\s+(\d+)\s+(\d+)[^\d]/) { # note: sqcount is not used
    0          
    0          
154 0           $data->{$name} = { format=>$format, samples=>$samples, count=>$count };
155             }
156             elsif(my($rqname,$rqx,$rqformat) = $_ =~ /^(\S+)\s+(\d+) samples \[(.+)\]/) {
157 0           $data->{$rqname} = { format=>$rqformat, samples=>$rqx, count=>$rqx };
158             }
159             elsif($_ =~ /^snapshot_time\s+([0-9.]+) /) {
160 0           $snap = $1;
161             }
162             }
163 0           close(P);
164 0           return({ timestamp=>$snap, data=>$data });
165             }
166              
167             ##########################################################################
168             # Try to parse the per-export 'brw' statistics file
169             sub _parse_brw_file {
170 0     0     my($self,$fname) = @_;
171            
172 0           my $ctx = '';
173 0           my $r = {};
174 0 0         open(P, $fname) or return undef;
175 0           while(

) {

176 0 0 0       if($_ =~ /^snapshot_time:\s+([0-9.]+) /) {
    0          
    0          
    0          
177 0           $r->{timestamp} = $1;
178             }
179             elsif($_ =~ /([^:]+?)(\s+)ios .+ ios/) {
180 0           $ctx = lc($1);
181 0           $ctx =~ tr/a-z0-9/_/c;
182             }
183             elsif($_ =~ /^$/) {
184 0           $ctx = '';
185             }
186             elsif($ctx && $_ =~ /^(.+):\s+(\d+)\s+\d+\s+\d+\s+\|\s*(\d+)\s+\d+/) {
187 0           $r->{data}->{$ctx}->{$1} = { read=>$2, write=>$3 };
188             }
189             }
190 0           close(P);
191 0           return $r;
192             }
193              
194              
195             ##########################################################################
196             # Quick'n'dirty 'generic' parser
197             sub _parse_generic_file {
198 0     0     my($self,$fname) = @_;
199            
200 0           my $r = {};
201 0 0         open(P, $fname) or return undef;
202 0           while(

) {

203 0 0         if(my($k,$v) = $_ =~ /^(\S+):\s+(.+)$/) {
204 0 0         if($v =~ /^(\d+)\/(\d+)$/) {
205 0           $v = [$1,$2];
206             }
207 0           $r->{$k} = $v;
208             }
209             }
210 0           close(P);
211 0           return $r;
212             }
213              
214             ##########################################################################
215             # Perform an addition on multiple deep hashrefs
216             # This could also be implemented by using recursion but perl is somewhat
217             # slow wehn it comes to call sub()'s, so eval should be faster for very
218             # 'deep' hashes.
219             sub sum_up_deep {
220 0     0 0   my($self, $size, @reflist) = @_;
221            
222 0           my $to_eval_h = '';
223 0           my $to_eval_m = '';
224 0           my $to_eval_b = '';
225 0           my $eval_code = undef;
226 0           my $res = {};
227 0           foreach my $tnum (0..$size) {
228 0           my $nnum = $tnum+1;
229 0           my $xtab = ( " " x $tnum );
230 0           $to_eval_h .= "${xtab}foreach my \$l$nnum (keys(%{\$lroot$to_eval_m})) {\n";
231 0           $to_eval_b = "$xtab}\n$to_eval_b";
232 0           $to_eval_m .= "->{\$l$nnum}";
233             }
234            
235             # Assemble perl-loop-code:
236 0           $eval_code = "$to_eval_h\t\t\$res$to_eval_m += \$lroot$to_eval_m\n".$to_eval_b;
237            
238             #..and execute for each given hashref
239 0           foreach my $lroot (@reflist) {
240 0           eval $eval_code;
241 0 0         return undef if $@; # error? -> most likely caused by an invalid $size setting!
242             }
243 0           return $res;
244             }
245              
246              
247             1;
248             __END__