mirror of
https://github.com/percona/percona-toolkit.git
synced 2025-09-10 13:11:32 +00:00
Automatic headers & improvements.
This commit is contained in:
167
bin/pt-diskstats
167
bin/pt-diskstats
@@ -1533,6 +1533,10 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
use IO::Handle;
|
||||
use List::Util qw( max first );
|
||||
|
||||
use ReadKeyMini qw( GetTerminalSize );
|
||||
|
||||
my (undef, $max_lines) = GetTerminalSize;
|
||||
|
||||
my $diskstat_colno_for;
|
||||
BEGIN {
|
||||
$diskstat_colno_for = {
|
||||
@@ -1576,9 +1580,11 @@ sub new {
|
||||
block_size => 512,
|
||||
show_inactive => $o->get('show-inactive'),
|
||||
sample_time => $o->get('sample-time') || 0,
|
||||
automatic_headers => $o->get('automatic-headers'),
|
||||
columns_regex => qr/$columns/,
|
||||
devices_regex => $devices ? qr/$devices/ : undef,
|
||||
interactive => 0,
|
||||
force_header => 1,
|
||||
|
||||
%args,
|
||||
|
||||
@@ -1606,13 +1612,38 @@ sub new {
|
||||
_nochange_skips => [],
|
||||
|
||||
_save_curr_as_prev => 1,
|
||||
_print_header => 1,
|
||||
};
|
||||
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
|
||||
sub active_device {
|
||||
my ( $self, $dev ) = @_;
|
||||
return $self->{_active_devices}->{$dev};
|
||||
}
|
||||
|
||||
sub set_active_device {
|
||||
my ($self, $dev, $val) = @_;
|
||||
return $self->{_active_devices}->{$dev} = $val;
|
||||
}
|
||||
|
||||
sub clear_active_devices {
|
||||
my ( $self ) = @_;
|
||||
return $self->{_active_devices} = {};
|
||||
}
|
||||
|
||||
|
||||
sub automatic_headers {
|
||||
my ($self) = @_;
|
||||
return $self->{automatic_headers};
|
||||
}
|
||||
|
||||
sub set_automatic_headers {
|
||||
my ($self, $new_val) = @_;
|
||||
return $self->{automatic_headers} = $new_val;
|
||||
}
|
||||
|
||||
sub curr_ts {
|
||||
my ($self) = @_;
|
||||
return $self->{_ts}->{curr} || 0;
|
||||
@@ -1732,9 +1763,19 @@ sub add_ordered_dev {
|
||||
}
|
||||
|
||||
|
||||
sub force_header {
|
||||
my ($self) = @_;
|
||||
return $self->{force_header};
|
||||
}
|
||||
|
||||
sub set_force_header {
|
||||
my ($self, $new_val) = @_;
|
||||
return $self->{force_header} = $new_val;
|
||||
}
|
||||
|
||||
sub clear_state {
|
||||
my ($self) = @_;
|
||||
$self->{_print_header} = 1;
|
||||
$self->set_force_header(1);
|
||||
$self->clear_curr_stats();
|
||||
$self->clear_prev_stats();
|
||||
$self->clear_first_stats();
|
||||
@@ -2159,22 +2200,39 @@ sub _print_device_if {
|
||||
my $dev_re = $self->devices_regex();
|
||||
|
||||
if ( $dev_re ) {
|
||||
$self->_mark_if_active($dev);
|
||||
return $dev if $dev =~ $dev_re;
|
||||
}
|
||||
else {
|
||||
if ( $self->show_inactive() || $self->active_device($dev) ) {
|
||||
if ( $self->active_device($dev) ) {
|
||||
return $dev;
|
||||
}
|
||||
elsif ( $self->show_inactive() ) {
|
||||
$self->_mark_if_active($dev);
|
||||
return $dev;
|
||||
}
|
||||
else {
|
||||
return $dev if $self->_mark_if_active($dev);
|
||||
}
|
||||
}
|
||||
push @{$self->{_nochange_skips}}, $dev;
|
||||
return;
|
||||
}
|
||||
|
||||
sub _mark_if_active {
|
||||
my ($self, $dev) = @_;
|
||||
|
||||
return $dev if $self->active_device($dev);
|
||||
|
||||
my $curr = $self->stats_for($dev);
|
||||
my $first = $self->first_stats_for($dev);
|
||||
|
||||
return unless $curr && $first;
|
||||
|
||||
if ( first { $curr->[$_] != $first->[$_] } READS..MS_WEIGHTED ) {
|
||||
$self->set_active_device($dev, 1);
|
||||
return $dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
push @{$self->{_nochange_skips}}, $dev;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2240,32 +2298,30 @@ sub _calc_deltas {
|
||||
return $self->_calc_stats_for_deltas($elapsed);
|
||||
}
|
||||
|
||||
sub force_print_header {
|
||||
my ($self, @args) = @_;
|
||||
my $orig = $self->force_header();
|
||||
$self->force_header(1);
|
||||
$self->print_header(@args);
|
||||
$self->force_header($orig);
|
||||
return;
|
||||
}
|
||||
|
||||
sub print_header {
|
||||
my ($self, $header, @args) = @_;
|
||||
if ( $self->{_print_header} ) {
|
||||
if ( $self->force_header() ) {
|
||||
printf $header . "\n", @args;
|
||||
$Diskstats::printed_lines--;
|
||||
$Diskstats::printed_lines ||= $max_lines;
|
||||
}
|
||||
}
|
||||
|
||||
sub active_device {
|
||||
my ( $self, $dev ) = @_;
|
||||
return $self->{_active_devices}->{$dev};
|
||||
}
|
||||
|
||||
sub set_active_device {
|
||||
my ($self, $dev, $val) = @_;
|
||||
return $self->{_active_devices}->{$dev} = $val;
|
||||
}
|
||||
|
||||
sub clear_active_devices {
|
||||
my ( $self ) = @_;
|
||||
return $self->{_active_devices} = {};
|
||||
return;
|
||||
}
|
||||
|
||||
sub print_rows {
|
||||
my ($self, $format, $cols, $stat) = @_;
|
||||
|
||||
printf $format . "\n", @{ $stat }{ qw( line_ts dev ), @$cols };
|
||||
$Diskstats::printed_lines--;
|
||||
}
|
||||
|
||||
sub print_deltas {
|
||||
@@ -2283,11 +2339,28 @@ sub print_deltas {
|
||||
my $header_method = $args{header_callback} || "print_header";
|
||||
my $rows_method = $args{rows_callback} || "print_rows";
|
||||
|
||||
$Diskstats::printed_lines ||= $max_lines;
|
||||
|
||||
$self->$header_method( $header, "#ts", "device" );
|
||||
|
||||
foreach my $stat ( $self->_calc_deltas() ) {
|
||||
my @stats = $self->_calc_deltas();
|
||||
|
||||
while ( my @stats_chunk = splice @stats, 0, $Diskstats::printed_lines ) {
|
||||
foreach my $stat ( @stats_chunk ) {
|
||||
$self->$rows_method( $format, $cols, $stat );
|
||||
}
|
||||
|
||||
if ( $Diskstats::printed_lines == 0 ) {
|
||||
$Diskstats::printed_lines ||= $max_lines;
|
||||
|
||||
if ( $self->automatic_headers()
|
||||
&& !$self->isa("DiskstatsGroupByAll") )
|
||||
{
|
||||
local $self->{force_header} = 1;
|
||||
$self->$header_method( $header, "#ts", "device" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub compute_line_ts {
|
||||
@@ -2473,7 +2546,6 @@ sub new {
|
||||
my ($class, %args) = @_;
|
||||
my $self = $class->SUPER::new(%args);
|
||||
$self->{_iterations} = 0;
|
||||
$self->{_print_header} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
@@ -2502,12 +2574,12 @@ sub group_by {
|
||||
header_callback => sub {
|
||||
my ($self, @args) = @_;
|
||||
|
||||
if ( $self->{_print_header} ) {
|
||||
if ( $self->force_header() ) {
|
||||
my $method = $args{header_callback}
|
||||
|| "print_header";
|
||||
$self->$method(@args);
|
||||
}
|
||||
$self->{_print_header} = undef;
|
||||
$self->set_force_header(undef);
|
||||
},
|
||||
rows_callback => $args{rows_callback},
|
||||
);
|
||||
@@ -2546,10 +2618,10 @@ sub group_by {
|
||||
|
||||
sub clear_state {
|
||||
my ($self, @args) = @_;
|
||||
my $orig_print_h = $self->{_print_header};
|
||||
my $orig_print_h = $self->{force_header};
|
||||
$self->{_iterations} = 0;
|
||||
$self->SUPER::clear_state(@args);
|
||||
$self->{_print_header} = $orig_print_h;
|
||||
$self->{force_header} = $orig_print_h;
|
||||
}
|
||||
|
||||
sub compute_line_ts {
|
||||
@@ -2618,7 +2690,6 @@ sub new {
|
||||
my $self = $class->SUPER::new(%args);
|
||||
$self->{_iterations} = 0;
|
||||
$self->{_save_curr_as_prev} = 0;
|
||||
$self->{_print_header} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
@@ -2658,10 +2729,10 @@ sub _sample_callback {
|
||||
header_callback => sub {
|
||||
my ( $self, $header, @args ) = @_;
|
||||
|
||||
if ( $self->{_print_header} ) {
|
||||
if ( $self->force_header() ) {
|
||||
my $method = $args{header_callback} || "print_header";
|
||||
$self->$method( $header, @args );
|
||||
$self->{_print_header} = undef;
|
||||
$self->set_force_header(undef);
|
||||
}
|
||||
},
|
||||
rows_callback => sub {
|
||||
@@ -2694,7 +2765,6 @@ sub clear_state {
|
||||
my ( $self, @args ) = @_;
|
||||
$self->{_iterations} = 0;
|
||||
$self->{_save_curr_as_prev} = 0;
|
||||
$self->{_print_header} = 1;
|
||||
$self->SUPER::clear_state(@args);
|
||||
}
|
||||
|
||||
@@ -2842,8 +2912,11 @@ my %actions = (
|
||||
"Enter a disk/device pattern: " ),
|
||||
'q' => sub { return 'last' },
|
||||
'p' => sub {
|
||||
my (@args) = @_;
|
||||
print "Paused - press any key to continue\n";
|
||||
pause(@_);
|
||||
pause(@args);
|
||||
$Diskstats::printed_lines--;
|
||||
print_header(@args) unless $Diskstats::printed_lines;
|
||||
return;
|
||||
},
|
||||
' ' => \&print_header,
|
||||
@@ -2957,8 +3030,8 @@ sub run_interactive {
|
||||
&& !grep { $input eq $_ } qw( A S D ), ' ', "\n" )
|
||||
{
|
||||
my $obj = $o->get("current_group_by_obj");
|
||||
local $obj->{_print_header} = 1;
|
||||
$obj->clear_state();
|
||||
local $obj->{force_header} = 1;
|
||||
group_by(
|
||||
select_obj => $sel,
|
||||
OptionParser => $o,
|
||||
@@ -3046,8 +3119,7 @@ sub print_header {
|
||||
|
||||
my $obj = $o->get("current_group_by_obj");
|
||||
my ($header) = $obj->design_print_formats();
|
||||
local $obj->{_print_header} = 1;
|
||||
return $obj->print_header($header, "#ts", "device");
|
||||
return $obj->force_print_header($header, "#ts", "device");
|
||||
}
|
||||
|
||||
sub group_by {
|
||||
@@ -3089,7 +3161,7 @@ sub group_by {
|
||||
header_callback => $header_callback,
|
||||
);
|
||||
$obj->set_interactive(1);
|
||||
$obj->{_print_header} = 0;
|
||||
$obj->set_force_header(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3107,7 +3179,7 @@ sub help {
|
||||
$re ||= '(none)';
|
||||
}
|
||||
|
||||
print <<"HELP";
|
||||
my $help = <<"HELP";
|
||||
You can control this program by key presses:
|
||||
------------------- Key ------------------- ---- Current Setting ----
|
||||
A, D, S) Set the group-by mode $mode
|
||||
@@ -3120,7 +3192,17 @@ sub help {
|
||||
q) Quit the program
|
||||
------------------- Press any key to continue -----------------------
|
||||
HELP
|
||||
pause(@_);
|
||||
print $help;
|
||||
=begin IGNORE
|
||||
|
||||
my $lines = $help =~ tr/\n//;
|
||||
|
||||
while ( $lines-- ) {
|
||||
$Diskstats::printed_lines--;
|
||||
print_header(%args) unless $Diskstats::printed_lines;
|
||||
}
|
||||
=cut
|
||||
pause(%args);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3169,6 +3251,7 @@ sub get_blocking_input {
|
||||
|
||||
ReadKeyMini::cbreak();
|
||||
STDIN->blocking(0);
|
||||
|
||||
return $new_opt;
|
||||
}
|
||||
|
||||
@@ -3553,6 +3636,12 @@ When in interactive mode, wait N seconds before printing to the screen.
|
||||
|
||||
Show inactive devices.
|
||||
|
||||
=item --[no]automatic-headers
|
||||
|
||||
default: yes
|
||||
|
||||
Print the headers as often as needed to prevent it from scrolling out of view.
|
||||
|
||||
=item --help
|
||||
|
||||
Show help and exit.
|
||||
|
129
lib/Diskstats.pm
129
lib/Diskstats.pm
@@ -32,6 +32,10 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0;
|
||||
use IO::Handle;
|
||||
use List::Util qw( max first );
|
||||
|
||||
use ReadKeyMini qw( GetTerminalSize );
|
||||
|
||||
my (undef, $max_lines) = GetTerminalSize;
|
||||
|
||||
my $diskstat_colno_for;
|
||||
BEGIN {
|
||||
$diskstat_colno_for = {
|
||||
@@ -79,9 +83,11 @@ sub new {
|
||||
block_size => 512,
|
||||
show_inactive => $o->get('show-inactive'),
|
||||
sample_time => $o->get('sample-time') || 0,
|
||||
automatic_headers => $o->get('automatic-headers'),
|
||||
columns_regex => qr/$columns/,
|
||||
devices_regex => $devices ? qr/$devices/ : undef,
|
||||
interactive => 0,
|
||||
force_header => 1,
|
||||
|
||||
%args,
|
||||
|
||||
@@ -110,7 +116,6 @@ sub new {
|
||||
|
||||
# Internal for now, but might need APIfying.
|
||||
_save_curr_as_prev => 1,
|
||||
_print_header => 1,
|
||||
};
|
||||
|
||||
return bless $self, $class;
|
||||
@@ -118,6 +123,32 @@ sub new {
|
||||
|
||||
# The next lot are accessors, plus some convenience functions.
|
||||
|
||||
sub active_device {
|
||||
my ( $self, $dev ) = @_;
|
||||
return $self->{_active_devices}->{$dev};
|
||||
}
|
||||
|
||||
sub set_active_device {
|
||||
my ($self, $dev, $val) = @_;
|
||||
return $self->{_active_devices}->{$dev} = $val;
|
||||
}
|
||||
|
||||
sub clear_active_devices {
|
||||
my ( $self ) = @_;
|
||||
return $self->{_active_devices} = {};
|
||||
}
|
||||
|
||||
|
||||
sub automatic_headers {
|
||||
my ($self) = @_;
|
||||
return $self->{automatic_headers};
|
||||
}
|
||||
|
||||
sub set_automatic_headers {
|
||||
my ($self, $new_val) = @_;
|
||||
return $self->{automatic_headers} = $new_val;
|
||||
}
|
||||
|
||||
sub curr_ts {
|
||||
my ($self) = @_;
|
||||
return $self->{_ts}->{curr} || 0;
|
||||
@@ -242,9 +273,19 @@ sub add_ordered_dev {
|
||||
# clear_stuff methods. Like the name says, they clear state stored inside
|
||||
# the object.
|
||||
|
||||
sub force_header {
|
||||
my ($self) = @_;
|
||||
return $self->{force_header};
|
||||
}
|
||||
|
||||
sub set_force_header {
|
||||
my ($self, $new_val) = @_;
|
||||
return $self->{force_header} = $new_val;
|
||||
}
|
||||
|
||||
sub clear_state {
|
||||
my ($self) = @_;
|
||||
$self->{_print_header} = 1;
|
||||
$self->set_force_header(1);
|
||||
$self->clear_curr_stats();
|
||||
$self->clear_prev_stats();
|
||||
$self->clear_first_stats();
|
||||
@@ -740,26 +781,44 @@ sub _print_device_if {
|
||||
# device_regex was set explicitly, either through --devices-regex,
|
||||
# or by using the d option in interactive mode, and not leaving
|
||||
# it blank
|
||||
$self->_mark_if_active($dev);
|
||||
return $dev if $dev =~ $dev_re;
|
||||
}
|
||||
else {
|
||||
if ( $self->show_inactive() || $self->active_device($dev) ) {
|
||||
if ( $self->active_device($dev) ) {
|
||||
# If --show-interactive is enabled, or we've seen
|
||||
# the device be active at least once.
|
||||
return $dev;
|
||||
}
|
||||
elsif ( $self->show_inactive() ) {
|
||||
$self->_mark_if_active($dev);
|
||||
return $dev;
|
||||
}
|
||||
else {
|
||||
return $dev if $self->_mark_if_active($dev);
|
||||
}
|
||||
}
|
||||
# Not active, add it to the list of skips for debugging.
|
||||
push @{$self->{_nochange_skips}}, $dev;
|
||||
return;
|
||||
}
|
||||
|
||||
sub _mark_if_active {
|
||||
my ($self, $dev) = @_;
|
||||
|
||||
return $dev if $self->active_device($dev);
|
||||
|
||||
my $curr = $self->stats_for($dev);
|
||||
my $first = $self->first_stats_for($dev);
|
||||
|
||||
return unless $curr && $first;
|
||||
|
||||
# read 'any' instead of 'first'
|
||||
if ( first { $curr->[$_] != $first->[$_] } READS..MS_WEIGHTED ) {
|
||||
# It's different from the first one. Mark as active and return.
|
||||
$self->set_active_device($dev, 1);
|
||||
return $dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
# Not active, add it to the list of skips for debugging.
|
||||
push @{$self->{_nochange_skips}}, $dev;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -827,32 +886,31 @@ sub _calc_deltas {
|
||||
return $self->_calc_stats_for_deltas($elapsed);
|
||||
}
|
||||
|
||||
# Always print a header, disgreard the value of $self->force_header()
|
||||
sub force_print_header {
|
||||
my ($self, @args) = @_;
|
||||
my $orig = $self->force_header();
|
||||
$self->force_header(1);
|
||||
$self->print_header(@args);
|
||||
$self->force_header($orig);
|
||||
return;
|
||||
}
|
||||
|
||||
sub print_header {
|
||||
my ($self, $header, @args) = @_;
|
||||
if ( $self->{_print_header} ) {
|
||||
if ( $self->force_header() ) {
|
||||
printf $header . "\n", @args;
|
||||
$Diskstats::printed_lines--;
|
||||
$Diskstats::printed_lines ||= $max_lines;
|
||||
}
|
||||
}
|
||||
|
||||
sub active_device {
|
||||
my ( $self, $dev ) = @_;
|
||||
return $self->{_active_devices}->{$dev};
|
||||
}
|
||||
|
||||
sub set_active_device {
|
||||
my ($self, $dev, $val) = @_;
|
||||
return $self->{_active_devices}->{$dev} = $val;
|
||||
}
|
||||
|
||||
sub clear_active_devices {
|
||||
my ( $self ) = @_;
|
||||
return $self->{_active_devices} = {};
|
||||
return;
|
||||
}
|
||||
|
||||
sub print_rows {
|
||||
my ($self, $format, $cols, $stat) = @_;
|
||||
|
||||
printf $format . "\n", @{ $stat }{ qw( line_ts dev ), @$cols };
|
||||
$Diskstats::printed_lines--;
|
||||
}
|
||||
|
||||
sub print_deltas {
|
||||
@@ -871,11 +929,34 @@ sub print_deltas {
|
||||
my $header_method = $args{header_callback} || "print_header";
|
||||
my $rows_method = $args{rows_callback} || "print_rows";
|
||||
|
||||
$Diskstats::printed_lines ||= $max_lines;
|
||||
|
||||
$self->$header_method( $header, "#ts", "device" );
|
||||
|
||||
foreach my $stat ( $self->_calc_deltas() ) {
|
||||
my @stats = $self->_calc_deltas();
|
||||
|
||||
# Split the stats in chunks no greater than how many lines
|
||||
# we have left until printing the next header.
|
||||
while ( my @stats_chunk = splice @stats, 0, $Diskstats::printed_lines ) {
|
||||
# Print the stats
|
||||
foreach my $stat ( @stats_chunk ) {
|
||||
$self->$rows_method( $format, $cols, $stat );
|
||||
}
|
||||
|
||||
if ( $Diskstats::printed_lines == 0 ) {
|
||||
# If zero, reset the counter
|
||||
$Diskstats::printed_lines ||= $max_lines;
|
||||
|
||||
# If we are automagically printing headers and aren't in
|
||||
# --group-by all,
|
||||
if ( $self->automatic_headers()
|
||||
&& !$self->isa("DiskstatsGroupByAll") )
|
||||
{
|
||||
local $self->{force_header} = 1;
|
||||
$self->$header_method( $header, "#ts", "device" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub compute_line_ts {
|
||||
|
@@ -34,7 +34,6 @@ sub new {
|
||||
my ($class, %args) = @_;
|
||||
my $self = $class->SUPER::new(%args);
|
||||
$self->{_iterations} = 0;
|
||||
$self->{_print_header} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
@@ -65,12 +64,12 @@ sub group_by {
|
||||
header_callback => sub {
|
||||
my ($self, @args) = @_;
|
||||
|
||||
if ( $self->{_print_header} ) {
|
||||
if ( $self->force_header() ) {
|
||||
my $method = $args{header_callback}
|
||||
|| "print_header";
|
||||
$self->$method(@args);
|
||||
}
|
||||
$self->{_print_header} = undef;
|
||||
$self->set_force_header(undef);
|
||||
},
|
||||
rows_callback => $args{rows_callback},
|
||||
);
|
||||
@@ -116,10 +115,10 @@ sub group_by {
|
||||
|
||||
sub clear_state {
|
||||
my ($self, @args) = @_;
|
||||
my $orig_print_h = $self->{_print_header};
|
||||
my $orig_print_h = $self->{force_header};
|
||||
$self->{_iterations} = 0;
|
||||
$self->SUPER::clear_state(@args);
|
||||
$self->{_print_header} = $orig_print_h;
|
||||
$self->{force_header} = $orig_print_h;
|
||||
}
|
||||
|
||||
sub compute_line_ts {
|
||||
|
@@ -35,7 +35,6 @@ sub new {
|
||||
my $self = $class->SUPER::new(%args);
|
||||
$self->{_iterations} = 0;
|
||||
$self->{_save_curr_as_prev} = 0;
|
||||
$self->{_print_header} = 1;
|
||||
return $self;
|
||||
}
|
||||
|
||||
@@ -86,10 +85,10 @@ sub _sample_callback {
|
||||
header_callback => sub {
|
||||
my ( $self, $header, @args ) = @_;
|
||||
|
||||
if ( $self->{_print_header} ) {
|
||||
if ( $self->force_header() ) {
|
||||
my $method = $args{header_callback} || "print_header";
|
||||
$self->$method( $header, @args );
|
||||
$self->{_print_header} = undef;
|
||||
$self->set_force_header(undef);
|
||||
}
|
||||
},
|
||||
rows_callback => sub {
|
||||
@@ -122,7 +121,6 @@ sub clear_state {
|
||||
my ( $self, @args ) = @_;
|
||||
$self->{_iterations} = 0;
|
||||
$self->{_save_curr_as_prev} = 0;
|
||||
$self->{_print_header} = 1;
|
||||
$self->SUPER::clear_state(@args);
|
||||
}
|
||||
|
||||
|
@@ -190,7 +190,7 @@ sub run_interactive {
|
||||
my $obj = $o->get("current_group_by_obj");
|
||||
# Force it to print the header
|
||||
$obj->clear_state();
|
||||
local $obj->{_print_header} = 1;
|
||||
local $obj->{force_header} = 1;
|
||||
group_by(
|
||||
select_obj => $sel,
|
||||
OptionParser => $o,
|
||||
@@ -291,8 +291,7 @@ sub print_header {
|
||||
|
||||
my $obj = $o->get("current_group_by_obj");
|
||||
my ($header) = $obj->design_print_formats();
|
||||
local $obj->{_print_header} = 1;
|
||||
return $obj->print_header($header, "#ts", "device");
|
||||
return $obj->force_print_header($header, "#ts", "device");
|
||||
}
|
||||
|
||||
sub group_by {
|
||||
@@ -341,7 +340,7 @@ sub group_by {
|
||||
header_callback => $header_callback,
|
||||
);
|
||||
$obj->set_interactive(1);
|
||||
$obj->{_print_header} = 0;
|
||||
$obj->set_force_header(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,7 +371,8 @@ sub help {
|
||||
q) Quit the program
|
||||
------------------- Press any key to continue -----------------------
|
||||
HELP
|
||||
pause(@_);
|
||||
|
||||
pause(%args);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -421,6 +421,7 @@ sub get_blocking_input {
|
||||
|
||||
ReadKeyMini::cbreak();
|
||||
STDIN->blocking(0);
|
||||
|
||||
return $new_opt;
|
||||
}
|
||||
|
||||
|
@@ -135,11 +135,8 @@ sub readkey {
|
||||
|
||||
# As per perlfaq8:
|
||||
|
||||
sub _GetTerminalSize {
|
||||
if ( @_ ) {
|
||||
die "My::Term::ReadKey doesn't implement GetTerminalSize with arguments";
|
||||
}
|
||||
eval { require 'sys/ioctl.ph' };
|
||||
BEGIN {
|
||||
eval { no warnings; local $^W; require 'sys/ioctl.ph' };
|
||||
if ( !defined &TIOCGWINSZ ) {
|
||||
*TIOCGWINSZ = sub () {
|
||||
# Very few systems actually have ioctl.ph, thus it comes to this.
|
||||
@@ -150,13 +147,37 @@ sub _GetTerminalSize {
|
||||
: 0x40087468;
|
||||
};
|
||||
}
|
||||
open( TTY, "+<", "/dev/tty" ) or die "No tty: $OS_ERROR";
|
||||
my $winsize = '';
|
||||
unless ( ioctl( TTY, &TIOCGWINSZ, $winsize ) ) {
|
||||
die sprintf "$0: ioctl TIOCGWINSZ (%08x: $OS_ERROR)\n", &TIOCGWINSZ;
|
||||
}
|
||||
|
||||
sub _GetTerminalSize {
|
||||
if ( @_ ) {
|
||||
die "My::Term::ReadKey doesn't implement GetTerminalSize with arguments";
|
||||
}
|
||||
my ( $row, $col, $xpixel, $ypixel ) = unpack( 'S4', $winsize );
|
||||
return ( $col, $row, $xpixel, $ypixel );
|
||||
|
||||
my ( $rows, $cols );
|
||||
|
||||
if ( open( TTY, "+<", "/dev/tty" ) ) { # Got a tty
|
||||
my $winsize = '';
|
||||
if ( ioctl( TTY, &TIOCGWINSZ, $winsize ) ) {
|
||||
( $rows, $cols, my ( $xpixel, $ypixel ) ) = unpack( 'S4', $winsize );
|
||||
return ( $cols, $rows, $xpixel, $ypixel );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $rows = `tput lines` ) {
|
||||
chomp($rows);
|
||||
chomp($cols = `tput cols`);
|
||||
}
|
||||
elsif ( my $stty = `stty -a` ) {
|
||||
($rows, $cols) = $stty =~ /([0-9]+) rows; ([0-9]+) columns;/;
|
||||
}
|
||||
else {
|
||||
($cols, $rows) = @ENV{qw( COLUMNS LINES )};
|
||||
$cols ||= 80;
|
||||
$rows ||= 24;
|
||||
}
|
||||
|
||||
return ( $cols, $rows );
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -322,12 +322,12 @@ is(
|
||||
"compute_line_ts has a sane default",
|
||||
);
|
||||
|
||||
$obj->{_print_header} = 0;
|
||||
$obj->set_force_header(0);
|
||||
|
||||
is(
|
||||
output( sub { $obj->print_header } ),
|
||||
output( sub { $obj->print_header("asdasdas") } ),
|
||||
"",
|
||||
"INTERNAL: _print_header works"
|
||||
"force_header works"
|
||||
);
|
||||
|
||||
my $output = output(
|
||||
@@ -472,6 +472,7 @@ for my $test (
|
||||
|
||||
$obj->set_columns_regex(qr/ \A (?!.*io_s$|\s*[qs]time$) /x);
|
||||
$obj->set_show_inactive(1);
|
||||
$obj->set_automatic_headers(0);
|
||||
|
||||
for my $filename ( map "diskstats-00$_.txt", 1..5 ) {
|
||||
my $file = File::Spec->catfile( "t", "pt-diskstats", "samples", $filename );
|
||||
|
@@ -57,7 +57,9 @@ sub test_diskstats_file {
|
||||
sub {
|
||||
tie local *STDIN, TestInteractive => @commands;
|
||||
pt_diskstats::main(
|
||||
qw(--show-inactive --group-by), $groupby,
|
||||
'--show-inactive',
|
||||
'--no-automatic-headers',
|
||||
'--group-by', $groupby,
|
||||
'--columns-regex','cnc|rt|mb|busy|prg',
|
||||
$file);
|
||||
},
|
||||
@@ -69,7 +71,6 @@ sub test_diskstats_file {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach my $file ( map "diskstats-00$_.txt", 1..5 ) {
|
||||
test_diskstats_file(file => $file);
|
||||
}
|
||||
|
Reference in New Issue
Block a user