~percona-toolkit-dev/percona-toolkit/fix-password-comma-bug-886077

« back to all changes in this revision

Viewing changes to lib/DiskstatsGroupBySample.pm

  • Committer: Daniel Nichter
  • Date: 2012-02-07 20:10:11 UTC
  • mfrom: (174 2.0)
  • mto: This revision was merged to the branch mainline in revision 189.
  • Revision ID: daniel@percona.com-20120207201011-sok2c1f2ay9qr3gm
Merge trunk r174.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# This program is copyright 2011 Percona Inc.
 
2
# Feedback and improvements are welcome.
 
3
#
 
4
# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 
5
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 
6
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 
7
#
 
8
# This program is free software; you can redistribute it and/or modify it under
 
9
# the terms of the GNU General Public License as published by the Free Software
 
10
# Foundation, version 2; OR the Perl Artistic License.  On UNIX and similar
 
11
# systems, you can issue `man perlgpl' or `man perlartistic' to read these
 
12
# licenses.
 
13
#
 
14
# You should have received a copy of the GNU General Public License along with
 
15
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
16
# Place, Suite 330, Boston, MA  02111-1307  USA.
 
17
# ###########################################################################
 
18
# DiskstatsGroupBySample package
 
19
# ###########################################################################
 
20
{
 
21
# Package: DiskstatsGroupBySample
 
22
#
 
23
 
 
24
package DiskstatsGroupBySample;
 
25
 
 
26
use warnings;
 
27
use strict;
 
28
use English qw(-no_match_vars);
 
29
use constant PTDEBUG => $ENV{PTDEBUG} || 0;
 
30
 
 
31
use base qw( Diskstats );
 
32
 
 
33
use POSIX qw( ceil );
 
34
 
 
35
sub new {
 
36
   my ( $class, %args ) = @_;
 
37
   my $self = $class->SUPER::new(%args);
 
38
   $self->{_iterations}        = 0;
 
39
   $self->{_save_curr_as_prev} = 0;
 
40
   return $self;
 
41
}
 
42
 
 
43
# Prints out one line for each disk, summing over the interval from first to
 
44
# last sample.
 
45
sub group_by {
 
46
   my ( $self, %args ) = @_;
 
47
   my @optional_args   = qw( header_callback rows_callback );
 
48
   my ( $header_callback, $rows_callback ) = $args{ @optional_args };
 
49
 
 
50
   $self->clear_state() unless $self->interactive();
 
51
 
 
52
   $self->parse_from(
 
53
      # ->can comes from UNIVERSAL. Returns a coderef to the method, if found.
 
54
      # undef otherwise.
 
55
      # Basically \&func, but always in runtime, and allows overriding
 
56
      # the method in child classes.
 
57
      sample_callback => $self->can("_sample_callback"),
 
58
      filehandle      => $args{filehandle},
 
59
      filename        => $args{filename},
 
60
      data            => $args{data},
 
61
   );
 
62
 
 
63
   return;
 
64
}
 
65
 
 
66
sub _sample_callback {
 
67
   my ( $self, $ts, %args ) = @_;
 
68
   my $printed_a_line = 0;
 
69
 
 
70
   if ( $self->has_stats() ) {
 
71
      $self->{_iterations}++;
 
72
   }
 
73
 
 
74
   my $elapsed = ($self->curr_ts() || 0)
 
75
               - ($self->prev_ts() || 0);
 
76
 
 
77
   if ( $ts > 0 && ceil($elapsed) >= $self->sample_time() ) {
 
78
 
 
79
      $self->print_deltas(
 
80
         # When grouping by samples, we don't usually show the device names,
 
81
         # only a count of how many devices each sample has, which causes the
 
82
         # columns' width change depending on simple invisible. That's uncalled
 
83
         # for, so we hardcode the width here
 
84
         # (6 is what the shell version used).
 
85
         max_device_length       => 6,
 
86
         header_callback         => sub {
 
87
            my ( $self, $header, @args ) = @_;
 
88
 
 
89
            if ( $self->force_header() ) {
 
90
               my $method = $args{header_callback} || "print_header";
 
91
               $self->$method( $header, @args );
 
92
               $self->set_force_header(undef);
 
93
            }
 
94
         },
 
95
         rows_callback => sub {
 
96
            my ( $self, $format, $cols, $stat ) = @_;
 
97
            my $method = $args{rows_callback} || "print_rows";
 
98
            $self->$method( $format, $cols, $stat );
 
99
            $printed_a_line = 1;
 
100
         }
 
101
      );
 
102
   }
 
103
   if ( $self->{_iterations} == 1 || $printed_a_line == 1 ) {
 
104
      $self->{_save_curr_as_prev} = 1;
 
105
      $self->_save_curr_as_prev( $self->stats_for() );
 
106
      $self->set_prev_ts_line( $self->curr_ts_line() );
 
107
      $self->{_save_curr_as_prev} = 0;
 
108
   }
 
109
   return;
 
110
}
 
111
 
 
112
sub delta_against {
 
113
   my ( $self, $dev ) = @_;
 
114
   return $self->prev_stats_for($dev);
 
115
}
 
116
 
 
117
sub ts_line_for_timestamp {
 
118
   my ($self) = @_;
 
119
   return $self->prev_ts_line();
 
120
}
 
121
 
 
122
sub delta_against_ts {
 
123
   my ( $self ) = @_;
 
124
   return $self->prev_ts();
 
125
}
 
126
 
 
127
sub clear_state {
 
128
   my ( $self, @args )         = @_;
 
129
   $self->{_iterations}        = 0;
 
130
   $self->{_save_curr_as_prev} = 0;
 
131
   $self->SUPER::clear_state(@args);
 
132
}
 
133
 
 
134
sub compute_devs_in_group {
 
135
   my ($self) = @_;
 
136
   my $stats  = $self->stats_for();
 
137
   return scalar grep {
 
138
            # Got stats for that device, and it matches the devices re
 
139
            $stats->{$_} && $self->_print_device_if($_)
 
140
         } $self->ordered_devs;
 
141
}
 
142
 
 
143
sub compute_dev {
 
144
   my ( $self, $devs ) = @_;
 
145
   $devs ||= $self->compute_devs_in_group();
 
146
   return $devs > 1
 
147
     ? "{" . $devs . "}"
 
148
     : $self->{_ordered_devs}->[0];
 
149
}
 
150
 
 
151
# Terrible breach of encapsulation, but it'll have to do for the moment.
 
152
sub _calc_stats_for_deltas {
 
153
   my ( $self, $elapsed ) = @_;
 
154
 
 
155
   my $delta_for;
 
156
 
 
157
   foreach my $dev ( grep { $self->_print_device_if($_) } $self->ordered_devs() ) {
 
158
      my $curr    = $self->stats_for($dev);
 
159
      my $against = $self->delta_against($dev);
 
160
 
 
161
      next unless $curr && $against;
 
162
 
 
163
      my $delta = $self->_calc_delta_for( $curr, $against );
 
164
      $delta->{ios_in_progress} = $curr->[Diskstats::IOS_IN_PROGRESS];
 
165
      while ( my ( $k, $v ) = each %$delta ) {
 
166
         $delta_for->{$k} += $v;
 
167
      }
 
168
   }
 
169
 
 
170
   return unless $delta_for && %{$delta_for};
 
171
 
 
172
   my $in_progress     = $delta_for->{ios_in_progress};
 
173
   my $tot_in_progress = 0;
 
174
   my $devs_in_group   = $self->compute_devs_in_group() || 1;
 
175
 
 
176
   my %stats = (
 
177
      $self->_calc_read_stats(
 
178
         delta_for     => $delta_for,
 
179
         elapsed       => $elapsed,
 
180
         devs_in_group => $devs_in_group,
 
181
      ),
 
182
      $self->_calc_write_stats(
 
183
         delta_for     => $delta_for,
 
184
         elapsed       => $elapsed,
 
185
         devs_in_group => $devs_in_group,
 
186
      ),
 
187
      in_progress =>
 
188
         $self->compute_in_progress( $in_progress, $tot_in_progress ),
 
189
   );
 
190
 
 
191
   my %extras = $self->_calc_misc_stats(
 
192
      delta_for     => $delta_for,
 
193
      elapsed       => $elapsed,
 
194
      devs_in_group => $devs_in_group,
 
195
      stats         => \%stats,
 
196
   );
 
197
 
 
198
   @stats{ keys %extras } = values %extras;
 
199
 
 
200
   $stats{dev} = $self->compute_dev( $devs_in_group );
 
201
 
 
202
   $self->{_first_time_magic} = undef;
 
203
   if ( @{$self->{_nochange_skips}} ) {
 
204
      my $devs = join ", ", @{$self->{_nochange_skips}};
 
205
      PTDEBUG && _d("Skipping [$devs], haven't changed from the first sample");
 
206
      $self->{_nochange_skips} = [];
 
207
   }
 
208
 
 
209
   return \%stats;
 
210
}
 
211
 
 
212
sub compute_line_ts {
 
213
   my ($self, %args) = @_;
 
214
   if ( $self->show_timestamps() ) {
 
215
      @args{ qw( first_ts curr_ts ) } = @args{ qw( curr_ts first_ts ) }
 
216
   }
 
217
   return $self->SUPER::compute_line_ts(%args);
 
218
}
 
219
 
 
220
1;
 
221
 
 
222
}
 
223
# ###########################################################################
 
224
# End DiskstatsGroupBySample package
 
225
# ###########################################################################