diff --git a/Changelog b/Changelog index 1fc2a2be..5ff66a01 100644 --- a/Changelog +++ b/Changelog @@ -1,5 +1,41 @@ Changelog for Percona Toolkit +v2.1.8 released 2012-12-21 + + * Beta support for MySQL 5.6 + * Beta support for Percona XtraDB Cluster + * pt-online-schema-change: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer + * pt-table-checksum: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer + * pt-upgrade: Added --[no]disable-query-cache + * Fixed bug 927955: Bad pod2rst transformation + * Fixed bug 898665: Bad online docs formatting for --[no]vars + * Fixed bug 1022622: pt-config-diff is case-sensitive + * Fixed bug 1007938: pt-config-diff doesn't handle end-of-line comments + * Fixed bug 917770: pt-config-diff Use of uninitialized value in substitution (s///) at line 1996 + * Fixed bug 1082104: pt-deadlock-logger doesn't handle usernames with dashes + * Fixed bug 886059: pt-heartbeat handles timezones inconsistently + * Fixed bug 1086259: pt-kill --log-dsn timestamp is wrong + * Fixed bug 1015590: pt-mysql-summary doesn't handle renamed variables in Percona Server 5.5 + * Fixed bug 1079341: pt-online-schema-change checks for foreign keys on MyISAM tables + * Fixed bug 823431: pt-query-advisor hangs on big queries + * Fixed bug 996069: pt-query-advisor RES.001 is incorrect + * Fixed bug 933465: pt-query-advisor false positive on RES.001 + * Fixed bug 937234: pt-query-advisor issues wrong RES.001 + * Fixed bug 1082599: pt-query-digest fails to parse timestamp with no query + * Fixed bug 1078838: pt-query-digest doesn't parse general log with "Connect user as user" + * Fixed bug 957442: pt-query-digest with custom --group-by throws error + * Fixed bug 887638: pt-query-digest prints negative byte offset + * Fixed bug 831525: pt-query-digest help output mangled + * Fixed bug 932614: pt-slave-restart CHANGE MASTER query causes error + * Fixed bug 1046440: pt-stalk purge_samples slows down checks + * Fixed bug 986847: pt-stalk does not report NFS iostat + * Fixed bug 1074179: pt-table-checksum doesn't ignore tables for --replicate-check-only + * Fixed bug 911385: pt-table-checksum v2 fails when --resume + --ignore-database is used + * Fixed bug 1041391: pt-table-checksum debug statement for "Chosen hash func" prints undef + * Fixed bug 1075638: pt-table-checksum Illegal division by zero at line 7950 + * Fixed bug 1052475: pt-table-checksum uninitialized value in numeric lt (<) at line 8611 + * Fixed bug 1078887: Tools let --set-vars clobber the required SQL mode + v2.1.7 released 2012-11-19 * Fixed bug 1080384: pt-table-checksum 2.1.6 crashes using PTDEBUG diff --git a/Makefile.PL b/Makefile.PL index 0d74b097..d4c4c4d4 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -2,7 +2,7 @@ use ExtUtils::MakeMaker; WriteMakefile( NAME => 'percona-toolkit', - VERSION => '2.1.7', + VERSION => '2.1.8', EXE_FILES => [ ], MAN1PODS => { 'docs/percona-toolkit.pod' => 'blib/man1/percona-toolkit.1p', diff --git a/bin/pt-align b/bin/pt-align index d170249d..dd497446 100755 --- a/bin/pt-align +++ b/bin/pt-align @@ -199,8 +199,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2010-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -218,6 +218,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-align 2.1.7 +pt-align 2.1.8 =cut diff --git a/bin/pt-archiver b/bin/pt-archiver index 774f54b4..f635f644 100755 --- a/bin/pt-archiver +++ b/bin/pt-archiver @@ -14,8 +14,12 @@ use warnings FATAL => 'all'; BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo OptionParser - Mo TableParser DSNParser VersionParser @@ -23,7 +27,6 @@ BEGIN { TableNibbler Daemon MasterSlave - VersionCheck HTTPMicro Pingback )); @@ -39,7 +42,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -47,6 +50,650 @@ our $VERSION = '2.1.7'; # End Percona::Toolkit package # ########################################################################### +# ########################################################################### +# Lmo::Utils package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + +BEGIN { + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} + +{ + no strict 'refs'; + sub _glob_for { + return \*{shift()} + } + + sub _stash_for { + return \%{ shift() . "::" }; + } +} + +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + + +our %TYPES = ( + Bool => sub { !$_[0] || (defined $_[0] && looks_like_number($_[0]) && $_[0] == 1) }, + Num => sub { defined $_[0] && looks_like_number($_[0]) }, + Int => sub { defined $_[0] && looks_like_number($_[0]) && $_[0] == int($_[0]) }, + Str => sub { defined $_[0] }, + Object => sub { defined $_[0] && blessed($_[0]) }, + FileHandle => sub { local $@; require IO::Handle; fileno($_[0]) && $_[0]->opened }, + + map { + my $type = /R/ ? $_ : uc $_; + $_ . "Ref" => sub { ref $_[0] eq $type } + } qw(Array Code Hash Regexp Glob Scalar) +); + +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} + +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; + + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; + } + + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; + } + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); + } +} + +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + +my %export_for; +sub import { + warnings->import(qw(FATAL all)); + strict->import(); + + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; + } + + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } + + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } + } + goto &$original_method + }; + } + + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) + } + goto &$original_method; + } + } + + _install_coderef "${caller}::$attribute" => $method; + + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } + + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } +} + +sub _has_handles { + my ($caller, $attribute, $args) = @_; + my $handles = $args->{handles}; + + my $ref = ref $handles; + my $kv; + if ( $ref eq ref [] ) { + $kv = { map { $_,$_ } @{$handles} }; + } + elsif ( $ref eq ref {} ) { + $kv = $handles; + } + elsif ( $ref eq ref qr// ) { + Carp::confess("Cannot delegate methods based on a Regexp without a type constraint (isa)") + unless $args->{isa}; + my $target_class = $args->{isa}; + $kv = { + map { $_, $_ } + grep { $_ =~ $handles } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } + keys %{ _stash_for $target_class } + }; + } + else { + Carp::confess("handles for $ref not yet implemented"); + } + + while ( my ($method, $target) = each %{$kv} ) { + my $name = _glob_for "${caller}::$method"; + Carp::confess("You cannot overwrite a locally defined method ($method) with a delegation") + if defined &$name; + + my ($target, @curried_args) = ref($target) ? @$target : $target; + *$name = sub { + my $self = shift; + my $delegate_to = $self->$attribute(); + my $error = "Cannot delegate $method to $target because the value of $attribute"; + Carp::confess("$error is not defined") unless $delegate_to; + Carp::confess("$error is not an object (got '$delegate_to')") + unless Scalar::Util::blessed($delegate_to) || (!ref($delegate_to) && $delegate_to->can($target)); + return $delegate_to->$target(@curried_args, @_); + } + } +} + +sub _set_package_isa { + my ($package, @new_isa) = @_; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; +} + +sub _set_inherited_metadata { + my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); + my $linearized_isa = mro::get_linear_isa($class); + my %new_metadata; + + for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); + %new_metadata = ( + %new_metadata, + %$isa_metadata, + ); + } + %$class_metadata = %new_metadata; +} + +sub unimport { + my $caller = scalar caller(); + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); +} + +sub Dumper { + require Data::Dumper; + local $Data::Dumper::Indent = 0; + local $Data::Dumper::Sortkeys = 0; + local $Data::Dumper::Quotekeys = 0; + local $Data::Dumper::Terse = 1; + + Data::Dumper::Dumper(@_) +} + +BEGIN { + if ($] >= 5.010) { + { local $@; require mro; } + } + else { + local $@; + eval { + require MRO::Compat; + } or do { + *mro::get_linear_isa = *mro::get_linear_isa_dfs = sub { + no strict 'refs'; + + my $classname = shift; + + my @lin = ($classname); + my %stored; + foreach my $parent (@{"$classname\::ISA"}) { + my $plin = mro::get_linear_isa_dfs($parent); + foreach (@$plin) { + next if exists $stored{$_}; + push(@lin, $_); + $stored{$_} = 1; + } + } + return \@lin; + }; + } + } +} + +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + +} +1; +} +# ########################################################################### +# End Lmo package +# ########################################################################### + # ########################################################################### # OptionParser package # This package is a copy without comments from the original. The original @@ -1072,457 +1719,6 @@ if ( PTDEBUG ) { # End OptionParser package # ########################################################################### -# ########################################################################### -# Mo package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/Mo.pm -# t/lib/Mo.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. - -{ - no strict 'refs'; - sub _glob_for { - return \*{shift()} - } - - sub _stash_for { - return \%{ shift() . "::" }; - } -} - -use strict; -use warnings qw( FATAL all ); - -use Carp (); -use Scalar::Util qw(looks_like_number blessed); - - -our %TYPES = ( - Bool => sub { !$_[0] || (defined $_[0] && looks_like_number($_[0]) && $_[0] == 1) }, - Num => sub { defined $_[0] && looks_like_number($_[0]) }, - Int => sub { defined $_[0] && looks_like_number($_[0]) && $_[0] == int($_[0]) }, - Str => sub { defined $_[0] }, - Object => sub { defined $_[0] && blessed($_[0]) }, - FileHandle => sub { local $@; require IO::Handle; fileno($_[0]) && $_[0]->opened }, - - map { - my $type = /R/ ? $_ : uc $_; - $_ . "Ref" => sub { ref $_[0] eq $type } - } qw(Array Code Hash Regexp Glob Scalar) -); - -our %metadata_for; -{ - package Mo::Object; - - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); - - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; - } - - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always - } - else { - $ref = { @_ }; - } - return $ref; - } -} - -my %export_for; -sub Mo::import { - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); - - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); - } - } - - return if $exports{M}; - - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; - } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; - - $metadata_for{$caller}{$attribute} = (); - - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } - } - }, - %exports, - ); - - $export_for{$caller} = [ keys %exports ]; - - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; - -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) -} - -sub _has_handles { - my ($caller, $attribute, $args) = @_; - my $handles = $args->{handles}; - - my $ref = ref $handles; - my $kv; - if ( $ref eq ref [] ) { - $kv = { map { $_,$_ } @{$handles} }; - } - elsif ( $ref eq ref {} ) { - $kv = $handles; - } - elsif ( $ref eq ref qr// ) { - Carp::confess("Cannot delegate methods based on a Regexp without a type constraint (isa)") - unless $args->{isa}; - my $target_class = $args->{isa}; - $kv = { - map { $_, $_ } - grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } - keys %{ _stash_for $target_class } - }; - } - else { - Carp::confess("handles for $ref not yet implemented"); - } - - while ( my ($method, $target) = each %{$kv} ) { - my $name = _glob_for "${caller}::$method"; - Carp::confess("You cannot overwrite a locally defined method ($method) with a delegation") - if defined &$name; - - my ($target, @curried_args) = ref($target) ? @$target : $target; - *$name = sub { - my $self = shift; - my $delegate_to = $self->$attribute(); - my $error = "Cannot delegate $method to $target because the value of $attribute"; - Carp::confess("$error is not defined") unless $delegate_to; - Carp::confess("$error is not an object (got '$delegate_to')") - unless Scalar::Util::blessed($delegate_to) || (!ref($delegate_to) && $delegate_to->can($target)); - return $delegate_to->$target(@curried_args, @_); - } - } -} - -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $inner_types = _nested_constraints($1, $2); - } - else { - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - return 1 if ! defined($value); - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - -sub _set_package_isa { - my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; -} - -sub _set_inherited_metadata { - my $class = shift; - my $linearized_isa = mro::get_linear_isa($class); - my %new_metadata; - - for my $isa_class (reverse @$linearized_isa) { - %new_metadata = ( - %new_metadata, - %{ $metadata_for{$isa_class} || {} }, - ); - } - $metadata_for{$class} = \%new_metadata; -} - -sub unimport { - my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; -} - -sub Dumper { - require Data::Dumper; - local $Data::Dumper::Indent = 0; - local $Data::Dumper::Sortkeys = 0; - local $Data::Dumper::Quotekeys = 0; - local $Data::Dumper::Terse = 1; - - Data::Dumper::Dumper(@_) -} - -BEGIN { - if ($] >= 5.010) { - { local $@; require mro; } - } - else { - local $@; - eval { - require MRO::Compat; - } or do { - *mro::get_linear_isa = *mro::get_linear_isa_dfs = sub { - no strict 'refs'; - - my $classname = shift; - - my @lin = ($classname); - my %stored; - foreach my $parent (@{"$classname\::ISA"}) { - my $plin = mro::get_linear_isa_dfs($parent); - foreach (@$plin) { - next if exists $stored{$_}; - push(@lin, $_); - $stored{$_} = 1; - } - } - return \@lin; - }; - } - } -} - -} -1; -} -# ########################################################################### -# End Mo package -# ########################################################################### - # ########################################################################### # TableParser package # This package is a copy without comments from the original. The original @@ -1744,7 +1940,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); @@ -2322,7 +2518,7 @@ sub _d { { package VersionParser; -use Mo; +use Lmo; use Scalar::Util qw(blessed); use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -2498,7 +2694,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } -no Mo; +no Lmo; 1; } # ########################################################################### @@ -3829,300 +4025,6 @@ sub _d { # End MasterSlave package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -4812,7 +4714,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -4888,10 +4789,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -4902,13 +4802,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -4938,7 +4838,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -5121,6 +5021,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -7555,8 +7699,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -7574,6 +7718,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-archiver 2.1.7 +pt-archiver 2.1.8 =cut diff --git a/bin/pt-config-diff b/bin/pt-config-diff index d8995b7f..39c607a3 100755 --- a/bin/pt-config-diff +++ b/bin/pt-config-diff @@ -14,6 +14,11 @@ use warnings FATAL => 'all'; BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo OptionParser DSNParser Cxn @@ -22,7 +27,6 @@ BEGIN { MySQLConfig MySQLConfigComparer ReportFormatter - VersionCheck HTTPMicro Pingback )); @@ -38,7 +42,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -46,6 +50,650 @@ our $VERSION = '2.1.7'; # End Percona::Toolkit package # ########################################################################### +# ########################################################################### +# Lmo::Utils package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + +BEGIN { + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} + +{ + no strict 'refs'; + sub _glob_for { + return \*{shift()} + } + + sub _stash_for { + return \%{ shift() . "::" }; + } +} + +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + + +our %TYPES = ( + Bool => sub { !$_[0] || (defined $_[0] && looks_like_number($_[0]) && $_[0] == 1) }, + Num => sub { defined $_[0] && looks_like_number($_[0]) }, + Int => sub { defined $_[0] && looks_like_number($_[0]) && $_[0] == int($_[0]) }, + Str => sub { defined $_[0] }, + Object => sub { defined $_[0] && blessed($_[0]) }, + FileHandle => sub { local $@; require IO::Handle; fileno($_[0]) && $_[0]->opened }, + + map { + my $type = /R/ ? $_ : uc $_; + $_ . "Ref" => sub { ref $_[0] eq $type } + } qw(Array Code Hash Regexp Glob Scalar) +); + +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} + +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; + + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; + } + + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; + } + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); + } +} + +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + +my %export_for; +sub import { + warnings->import(qw(FATAL all)); + strict->import(); + + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; + } + + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } + + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } + } + goto &$original_method + }; + } + + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) + } + goto &$original_method; + } + } + + _install_coderef "${caller}::$attribute" => $method; + + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } + + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } +} + +sub _has_handles { + my ($caller, $attribute, $args) = @_; + my $handles = $args->{handles}; + + my $ref = ref $handles; + my $kv; + if ( $ref eq ref [] ) { + $kv = { map { $_,$_ } @{$handles} }; + } + elsif ( $ref eq ref {} ) { + $kv = $handles; + } + elsif ( $ref eq ref qr// ) { + Carp::confess("Cannot delegate methods based on a Regexp without a type constraint (isa)") + unless $args->{isa}; + my $target_class = $args->{isa}; + $kv = { + map { $_, $_ } + grep { $_ =~ $handles } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } + keys %{ _stash_for $target_class } + }; + } + else { + Carp::confess("handles for $ref not yet implemented"); + } + + while ( my ($method, $target) = each %{$kv} ) { + my $name = _glob_for "${caller}::$method"; + Carp::confess("You cannot overwrite a locally defined method ($method) with a delegation") + if defined &$name; + + my ($target, @curried_args) = ref($target) ? @$target : $target; + *$name = sub { + my $self = shift; + my $delegate_to = $self->$attribute(); + my $error = "Cannot delegate $method to $target because the value of $attribute"; + Carp::confess("$error is not defined") unless $delegate_to; + Carp::confess("$error is not an object (got '$delegate_to')") + unless Scalar::Util::blessed($delegate_to) || (!ref($delegate_to) && $delegate_to->can($target)); + return $delegate_to->$target(@curried_args, @_); + } + } +} + +sub _set_package_isa { + my ($package, @new_isa) = @_; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; +} + +sub _set_inherited_metadata { + my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); + my $linearized_isa = mro::get_linear_isa($class); + my %new_metadata; + + for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); + %new_metadata = ( + %new_metadata, + %$isa_metadata, + ); + } + %$class_metadata = %new_metadata; +} + +sub unimport { + my $caller = scalar caller(); + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); +} + +sub Dumper { + require Data::Dumper; + local $Data::Dumper::Indent = 0; + local $Data::Dumper::Sortkeys = 0; + local $Data::Dumper::Quotekeys = 0; + local $Data::Dumper::Terse = 1; + + Data::Dumper::Dumper(@_) +} + +BEGIN { + if ($] >= 5.010) { + { local $@; require mro; } + } + else { + local $@; + eval { + require MRO::Compat; + } or do { + *mro::get_linear_isa = *mro::get_linear_isa_dfs = sub { + no strict 'refs'; + + my $classname = shift; + + my @lin = ($classname); + my %stored; + foreach my $parent (@{"$classname\::ISA"}) { + my $plin = mro::get_linear_isa_dfs($parent); + foreach (@$plin) { + next if exists $stored{$_}; + push(@lin, $_); + $stored{$_} = 1; + } + } + return \@lin; + }; + } + } +} + +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + +} +1; +} +# ########################################################################### +# End Lmo package +# ########################################################################### + # ########################################################################### # OptionParser package # This package is a copy without comments from the original. The original @@ -2641,8 +3289,7 @@ sub _d { { package ReportFormatter; -use strict; -use warnings FATAL => 'all'; +use Lmo; use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -2652,40 +3299,102 @@ use POSIX qw(ceil); eval { require Term::ReadKey }; my $have_term = $EVAL_ERROR ? 0 : 1; -sub new { - my ( $class, %args ) = @_; - my @required_args = qw(); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless $args{$arg}; - } - my $self = { - underline_header => 1, - line_prefix => '# ', - line_width => 78, - column_spacing => ' ', - extend_right => 0, - truncate_line_mark => '...', - column_errors => 'warn', - truncate_header_side => 'left', - strip_whitespace => 1, - %args, # args above can be overriden, args below cannot - n_cols => 0, - }; - if ( ($self->{line_width} || '') eq 'auto' ) { +has underline_header => ( + is => 'ro', + isa => 'Bool', + default => sub { 1 }, +); +has line_prefix => ( + is => 'ro', + isa => 'Str', + default => sub { '# ' }, +); +has line_width => ( + is => 'ro', + isa => 'Int', + default => sub { 78 }, +); +has column_spacing => ( + is => 'ro', + isa => 'Str', + default => sub { ' ' }, +); +has extend_right => ( + is => 'ro', + isa => 'Bool', + default => sub { '' }, +); +has truncate_line_mark => ( + is => 'ro', + isa => 'Str', + default => sub { '...' }, +); +has column_errors => ( + is => 'ro', + isa => 'Str', + default => sub { 'warn' }, +); +has truncate_header_side => ( + is => 'ro', + isa => 'Str', + default => sub { 'left' }, +); +has strip_whitespace => ( + is => 'ro', + isa => 'Bool', + default => sub { 1 }, +); +has title => ( + is => 'rw', + isa => 'Str', + predicate => 'has_title', +); + + +has n_cols => ( + is => 'rw', + isa => 'Int', + default => sub { 0 }, + init_arg => undef, +); + +has cols => ( + is => 'ro', + isa => 'ArrayRef', + init_arg => undef, + default => sub { [] }, + clearer => 'clear_cols', +); + +has lines => ( + is => 'ro', + isa => 'ArrayRef', + init_arg => undef, + default => sub { [] }, + clearer => 'clear_lines', +); + +has truncate_headers => ( + is => 'rw', + isa => 'Bool', + default => sub { undef }, + init_arg => undef, + clearer => 'clear_truncate_headers', +); + +sub BUILDARGS { + my $class = shift; + my $args = $class->SUPER::BUILDARGS(@_); + + if ( ($args->{line_width} || '') eq 'auto' ) { die "Cannot auto-detect line width because the Term::ReadKey module " . "is not installed" unless $have_term; - ($self->{line_width}) = GetTerminalSize(); + ($args->{line_width}) = GetTerminalSize(); + PTDEBUG && _d('Line width:', $args->{line_width}); } - PTDEBUG && _d('Line width:', $self->{line_width}); - return bless $self, $class; -} - -sub set_title { - my ( $self, $title ) = @_; - $self->{title} = $title; - return; + return $args; } sub set_columns { @@ -2701,7 +3410,7 @@ sub set_columns { die "Column does not have a name" unless defined $col_name; if ( $col->{width} ) { - $col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width}); + $col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width()); PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =', $col->{width_pct}, '%'); } @@ -2728,10 +3437,10 @@ sub set_columns { $col->{right_most} = 1 if $i == $#cols; - push @{$self->{cols}}, $col; + push @{$self->cols}, $col; } - $self->{n_cols} = scalar @cols; + $self->n_cols( scalar @cols ); if ( ($used_width || 0) > 100 ) { die "Total width_pct for all columns is >100%"; @@ -2741,15 +3450,15 @@ sub set_columns { my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols); PTDEBUG && _d('Line width left:', (100-$used_width), '%;', 'each auto width col:', $wid_per_col, '%'); - map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols; + map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols; } - $min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing}; + $min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing(); PTDEBUG && _d('min header width:', $min_hdr_wid); - if ( $min_hdr_wid > $self->{line_width} ) { + if ( $min_hdr_wid > $self->line_width() ) { PTDEBUG && _d('Will truncate headers because min header width', - $min_hdr_wid, '> line width', $self->{line_width}); - $self->{truncate_headers} = 1; + $min_hdr_wid, '> line width', $self->line_width()); + $self->truncate_headers(1); } return; @@ -2758,14 +3467,14 @@ sub set_columns { sub add_line { my ( $self, @vals ) = @_; my $n_vals = scalar @vals; - if ( $n_vals != $self->{n_cols} ) { + if ( $n_vals != $self->n_cols() ) { $self->_column_error("Number of values $n_vals does not match " - . "number of columns $self->{n_cols}"); + . "number of columns " . $self->n_cols()); } for my $i ( 0..($n_vals-1) ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value}; - if ( $self->{strip_whitespace} ) { + if ( $self->strip_whitespace() ) { $val =~ s/^\s+//g; $val =~ s/\s+$//; $vals[$i] = $val; @@ -2774,7 +3483,7 @@ sub add_line { $col->{min_val} = min($width, ($col->{min_val} || $width)); $col->{max_val} = max($width, ($col->{max_val} || $width)); } - push @{$self->{lines}}, \@vals; + push @{$self->lines}, \@vals; return; } @@ -2782,26 +3491,28 @@ sub get_report { my ( $self, %args ) = @_; $self->_calculate_column_widths(); - $self->_truncate_headers() if $self->{truncate_headers}; + if ( $self->truncate_headers() ) { + $self->_truncate_headers(); + } $self->_truncate_line_values(%args); my @col_fmts = $self->_make_column_formats(); - my $fmt = ($self->{line_prefix} || '') - . join($self->{column_spacing}, @col_fmts); + my $fmt = $self->line_prefix() + . join($self->column_spacing(), @col_fmts); PTDEBUG && _d('Format:', $fmt); (my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g; my @lines; - push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title}; + push @lines, $self->line_prefix() . $self->title() if $self->has_title(); push @lines, $self->_truncate_line( - sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}), + sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}), strip => 1, mark => '', ); - if ( $self->{underline_header} ) { - my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}}; + if ( $self->underline_header() ) { + my @underlines = map { '=' x $_->{print_width} } @{$self->cols}; push @lines, $self->_truncate_line( sprintf($fmt, map { $_ || '' } @underlines), mark => '', @@ -2812,19 +3523,23 @@ sub get_report { my $vals = $_; my $i = 0; my @vals = map { - my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value}; + my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value}; $val = '' if !defined $val; $val =~ s/\n/ /g; $val; } @$vals; my $line = sprintf($fmt, @vals); - if ( $self->{extend_right} ) { + if ( $self->extend_right() ) { $line; } else { $self->_truncate_line($line); } - } @{$self->{lines}}; + } @{$self->lines}; + + $self->clear_cols(); + $self->clear_lines(); + $self->clear_truncate_headers(); return join("\n", @lines) . "\n"; } @@ -2832,7 +3547,7 @@ sub get_report { sub truncate_value { my ( $self, $col, $val, $width, $side ) = @_; return $val if length $val <= $width; - return $val if $col->{right_most} && $self->{extend_right}; + return $val if $col->{right_most} && $self->extend_right(); $side ||= $col->{truncate_side}; my $mark = $col->{truncate_mark}; if ( $side eq 'right' ) { @@ -2852,8 +3567,8 @@ sub _calculate_column_widths { my ( $self ) = @_; my $extra_space = 0; - foreach my $col ( @{$self->{cols}} ) { - my $print_width = int($self->{line_width} * ($col->{width_pct} / 100)); + foreach my $col ( @{$self->cols} ) { + my $print_width = int($self->line_width() * ($col->{width_pct} / 100)); PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct}, 'char width:', $print_width, @@ -2877,7 +3592,7 @@ sub _calculate_column_widths { PTDEBUG && _d('Extra space:', $extra_space); while ( $extra_space-- ) { - foreach my $col ( @{$self->{cols}} ) { + foreach my $col ( @{$self->cols} ) { if ( $col->{auto_width} && ( $col->{print_width} < $col->{max_val} || $col->{print_width} < $col->{header_width}) @@ -2892,8 +3607,8 @@ sub _calculate_column_widths { sub _truncate_headers { my ( $self, $col ) = @_; - my $side = $self->{truncate_header_side}; - foreach my $col ( @{$self->{cols}} ) { + my $side = $self->truncate_header_side(); + foreach my $col ( @{$self->cols} ) { my $col_name = $col->{name}; my $print_width = $col->{print_width}; next if length $col_name <= $print_width; @@ -2906,10 +3621,10 @@ sub _truncate_headers { sub _truncate_line_values { my ( $self, %args ) = @_; - my $n_vals = $self->{n_cols} - 1; - foreach my $vals ( @{$self->{lines}} ) { + my $n_vals = $self->n_cols() - 1; + foreach my $vals ( @{$self->lines} ) { for my $i ( 0..$n_vals ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value}; my $width = length $val; @@ -2935,9 +3650,9 @@ sub _truncate_line_values { sub _make_column_formats { my ( $self ) = @_; my @col_fmts; - my $n_cols = $self->{n_cols} - 1; + my $n_cols = $self->n_cols() - 1; for my $i ( 0..$n_cols ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $width = $col->{right_most} && !$col->{right_justify} ? '' : $col->{print_width}; @@ -2950,12 +3665,12 @@ sub _make_column_formats { sub _truncate_line { my ( $self, $line, %args ) = @_; - my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark}; + my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark(); if ( $line ) { $line =~ s/\s+$// if $args{strip}; my $len = length($line); - if ( $len > $self->{line_width} ) { - $line = substr($line, 0, $self->{line_width} - length $mark); + if ( $len > $self->line_width() ) { + $line = substr($line, 0, $self->line_width() - length $mark); $line .= $mark if $mark; } } @@ -2965,7 +3680,7 @@ sub _truncate_line { sub _column_error { my ( $self, $err ) = @_; my $msg = "Column error: $err"; - $self->{column_errors} eq 'die' ? die $msg : warn $msg; + $self->column_errors() eq 'die' ? die $msg : warn $msg; return; } @@ -2977,306 +3692,13 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } +no Lmo; 1; } # ########################################################################### # End ReportFormatter package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -3966,7 +4388,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -4042,10 +4463,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -4056,13 +4476,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -4092,7 +4512,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -4275,6 +4695,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -4443,7 +5107,7 @@ sub main { foreach my $var ( sort keys %$diffs ) { $report->add_line($var, @{$diffs->{$var}}); } - $report->set_title( + $report->title( "$n_diffs config difference" . ($n_diffs > 1 ? 's' : '')); print $report->get_report(); } @@ -4853,8 +5517,7 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -4872,6 +5535,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-config-diff 2.1.7 +pt-config-diff 2.1.8 =cut diff --git a/bin/pt-deadlock-logger b/bin/pt-deadlock-logger index 9e351a0f..de994f58 100755 --- a/bin/pt-deadlock-logger +++ b/bin/pt-deadlock-logger @@ -15,12 +15,15 @@ BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit OptionParser - Mo + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo VersionParser Quoter DSNParser Daemon - VersionCheck HTTPMicro Pingback )); @@ -36,7 +39,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -1070,18 +1073,24 @@ if ( PTDEBUG ) { # ########################################################################### # ########################################################################### -# Mo package +# Lmo::Utils package # This package is a copy without comments from the original. The original # with comments and its test file can be found in the Bazaar repository at, -# lib/Mo.pm -# t/lib/Mo.t +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t # See https://launchpad.net/percona-toolkit for more information. # ########################################################################### { +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} { no strict 'refs'; @@ -1094,6 +1103,194 @@ our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. } } +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + use strict; use warnings qw( FATAL all ); @@ -1115,240 +1312,277 @@ our %TYPES = ( } qw(Array Code Hash Regexp Glob Scalar) ); -our %metadata_for; -{ - package Mo::Object; +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; } - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; } - else { - $ref = { @_ }; - } - return $ref; + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); } } +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + my %export_for; -sub Mo::import { - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); +sub import { + warnings->import(qw(FATAL all)); + strict->import(); - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; } - } - return if $exports{M}; + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; + goto &$original_method + }; + } - $metadata_for{$caller}{$attribute} = (); - - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) } - }, - %exports, - ); + goto &$original_method; + } + } - $export_for{$caller} = [ keys %exports ]; + _install_coderef "${caller}::$attribute" => $method; - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } } sub _has_handles { @@ -1370,8 +1604,8 @@ sub _has_handles { $kv = { map { $_, $_ } grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } keys %{ _stash_for $target_class } }; } @@ -1397,80 +1631,32 @@ sub _has_handles { } } -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $inner_types = _nested_constraints($1, $2); - } - else { - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - return 1 if ! defined($value); - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - sub _set_package_isa { my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; } sub _set_inherited_metadata { my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); my $linearized_isa = mro::get_linear_isa($class); my %new_metadata; for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); %new_metadata = ( %new_metadata, - %{ $metadata_for{$isa_class} || {} }, + %$isa_metadata, ); } - $metadata_for{$class} = \%new_metadata; + %$class_metadata = %new_metadata; } sub unimport { my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); } sub Dumper { @@ -1513,12 +1699,23 @@ BEGIN { } } +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + } 1; } # ########################################################################### -# End Mo package +# End Lmo package # ########################################################################### + # ########################################################################### # VersionParser package # This package is a copy without comments from the original. The original @@ -1530,7 +1727,7 @@ BEGIN { { package VersionParser; -use Mo; +use Lmo; use Scalar::Util qw(blessed); use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -1706,7 +1903,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } -no Mo; +no Lmo; 1; } # ########################################################################### @@ -2418,300 +2615,6 @@ sub _d { # End Daemon package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -3401,7 +3304,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -3477,10 +3379,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -3491,13 +3392,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -3527,7 +3428,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -3710,6 +3611,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -4766,8 +4911,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -4785,6 +4930,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-deadlock-logger 2.1.7 +pt-deadlock-logger 2.1.8 =cut diff --git a/bin/pt-diskstats b/bin/pt-diskstats index 4e7193df..0ccff69e 100755 --- a/bin/pt-diskstats +++ b/bin/pt-diskstats @@ -22,7 +22,6 @@ BEGIN { DiskstatsGroupByDisk DiskstatsGroupBySample DiskstatsMenu - VersionCheck HTTPMicro Pingback )); @@ -38,7 +37,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -1091,24 +1090,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -1240,6 +1241,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -3506,300 +3510,6 @@ sub _d { # End DiskstatsMenu package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -4489,7 +4199,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -4565,10 +4274,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -4579,13 +4287,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -4615,7 +4323,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -4798,6 +4506,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -5548,8 +5500,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2010-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -5567,6 +5519,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-diskstats 2.1.7 +pt-diskstats 2.1.8 =cut diff --git a/bin/pt-duplicate-key-checker b/bin/pt-duplicate-key-checker index 7c382bc6..2754a197 100755 --- a/bin/pt-duplicate-key-checker +++ b/bin/pt-duplicate-key-checker @@ -23,7 +23,6 @@ BEGIN { Daemon Schema SchemaIterator - VersionCheck HTTPMicro Pingback )); @@ -39,7 +38,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -394,7 +393,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); @@ -3372,300 +3371,6 @@ sub _d { # End SchemaIterator package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -4355,7 +4060,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -4431,10 +4135,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -4445,13 +4148,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -4481,7 +4184,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -4664,6 +4367,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -5416,8 +5363,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -5435,6 +5382,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-duplicate-key-checker 2.1.7 +pt-duplicate-key-checker 2.1.8 =cut diff --git a/bin/pt-fifo-split b/bin/pt-fifo-split index 37f8f693..06303be6 100755 --- a/bin/pt-fifo-split +++ b/bin/pt-fifo-split @@ -1549,8 +1549,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -1568,6 +1568,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-fifo-split 2.1.7 +pt-fifo-split 2.1.8 =cut diff --git a/bin/pt-find b/bin/pt-find index 89c4a6b7..810d357c 100755 --- a/bin/pt-find +++ b/bin/pt-find @@ -19,7 +19,6 @@ BEGIN { Quoter TableParser Daemon - VersionCheck HTTPMicro Pingback )); @@ -35,7 +34,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -1792,7 +1791,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); @@ -2184,300 +2183,6 @@ sub _d { # End Daemon package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -3167,7 +2872,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -3243,10 +2947,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -3257,13 +2960,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -3293,7 +2996,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -3476,6 +3179,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -4879,8 +4826,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -4898,6 +4845,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-find 2.1.7 +pt-find 2.1.8 =cut diff --git a/bin/pt-fingerprint b/bin/pt-fingerprint index 4595bc02..973b4f4c 100755 --- a/bin/pt-fingerprint +++ b/bin/pt-fingerprint @@ -2129,8 +2129,7 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2012 Percona Ireland Ltd. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -2148,6 +2147,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-fingerprint 2.1.7 +pt-fingerprint 2.1.8 =cut diff --git a/bin/pt-fk-error-logger b/bin/pt-fk-error-logger index e09cf965..9de07934 100755 --- a/bin/pt-fk-error-logger +++ b/bin/pt-fk-error-logger @@ -19,7 +19,6 @@ BEGIN { DSNParser Daemon Transformers - VersionCheck HTTPMicro Pingback )); @@ -35,7 +34,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -1793,24 +1792,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -2124,300 +2125,6 @@ sub _d { # End Transformers package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -3107,7 +2814,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -3183,10 +2889,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -3197,13 +2902,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -3233,7 +2938,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -3416,6 +3121,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -4011,8 +3960,7 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2012 Percona Ireland Ltd. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -4030,6 +3978,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-fk-error-logger 2.1.7 +pt-fk-error-logger 2.1.8 =cut diff --git a/bin/pt-heartbeat b/bin/pt-heartbeat index 7cf8b44b..2b43d9ee 100755 --- a/bin/pt-heartbeat +++ b/bin/pt-heartbeat @@ -22,7 +22,6 @@ BEGIN { TableParser Retry Transformers - VersionCheck HTTPMicro Pingback )); @@ -38,7 +37,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -2731,7 +2730,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); @@ -3019,24 +3018,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -3168,6 +3169,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -3347,300 +3351,6 @@ sub _d { # End Transformers package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -4330,7 +4040,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -4406,10 +4115,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -4420,13 +4128,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -4456,7 +4164,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -4639,6 +4347,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -4804,6 +4756,8 @@ sub main { # ######################################################################## # Create the heartbeat table if --create-table was given. # ######################################################################## + my $utc = $o->get('utc'); + my $now_func = $utc ? 'UTC_TIMESTAMP()' : 'NOW()'; my $db_tbl = $q->quote($db, $tbl); my $server_id = $dbh->selectrow_array('SELECT @@server_id'); if ( $o->get('create-table') ) { @@ -4813,7 +4767,7 @@ sub main { $dbh->do($sql); $sql = ($o->get('replace') ? "REPLACE" : "INSERT") - . qq/ INTO $db_tbl (ts, server_id) VALUES (UTC_TIMESTAMP(), $server_id)/; + . qq/ INTO $db_tbl (ts, server_id) VALUES ($now_func, $server_id)/; PTDEBUG && _d($sql); # This may fail if the table already existed and already had this row. # We eval to ignore this possibility. @@ -4910,7 +4864,7 @@ sub main { PTDEBUG && _d('No heartbeat row in table'); if ( $o->get('insert-heartbeat-row') ) { my $sql = "INSERT INTO $db_tbl ($pk_col, ts) " - . "VALUES ('$pk_val', UTC_TIMESTAMP())"; + . "VALUES ('$pk_val', $now_func)"; PTDEBUG && _d($sql); $dbh->do($sql); } @@ -5004,8 +4958,7 @@ sub main { tries => 3, wait => sub { sleep 0.25; return; }, try => sub { - my ($now) = $dbh->selectrow_array(q{SELECT UTC_TIMESTAMP()}); - $sth->execute($now, @vals); + $sth->execute(ts(time, $utc), @vals); PTDEBUG && _d($sth->{Statement}); $sth->finish(); }, @@ -5036,7 +4989,7 @@ sub main { # UNIX_TIMESTAMP(ts) replaces unix_timestamp($ts) -- MySQL is the # authority here, so let it calculate everything. $heartbeat_sql - = "SELECT UNIX_TIMESTAMP(UTC_TIMESTAMP()), UNIX_TIMESTAMP(ts)" + = "SELECT " . ($utc ? 'UNIX_TIMESTAMP(ts)' : 'ts') . ($dbi_driver eq 'mysql' ? '/*!50038, @@hostname AS host*/' : '') . ($id ? "" : ", server_id") . " FROM $db_tbl " @@ -5050,12 +5003,13 @@ sub main { my ($sth) = @_; $sth->execute(); PTDEBUG && _d($sth->{Statement}); - my ($now, $ts, $hostname, $server_id) = $sth->fetchrow_array(); + my ($ts, $hostname, $server_id) = $sth->fetchrow_array(); + my $now = time; PTDEBUG && _d("Heartbeat from server", $server_id, "\n", - " now:", $now, "\n", + " now:", ts($now, $utc), "\n", " ts:", $ts, "\n", "skew:", $skew); - my $delay = $now - $ts - $skew; + my $delay = $now - unix_timestamp($ts, $utc) - $skew; PTDEBUG && _d('Delay', sprintf('%.6f', $delay), 'on', $hostname); # Because we adjust for skew, if the ts are less than skew seconds @@ -5860,6 +5814,16 @@ short form: -u; type: string User for login if not current user. +=item --utc + +Ignore system time zones and use only UTC. By default pt-heartbeat does +not check or adjust for different system or MySQL time zones which can +cause the tool to compute the lag incorrectly. Specifying this option is +a good idea because it ensures that the tool works correctly regardless of +time zones, but it also makes the tool backwards-incompatible with +pt-heartbeat 2.1.7 and older (unless the older version of pt-heartbeat +is running on a system that uses UTC). + =item --version Show version and exit. @@ -6023,9 +5987,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2006 Proven Scaling LLC and Six Apart Ltd, -2007-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2007-2013 Percona Ireland Ltd, +2006 Proven Scaling LLC and Six Apart Ltd. Feedback and improvements are welcome. @@ -6045,6 +6008,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-heartbeat 2.1.7 +pt-heartbeat 2.1.8 =cut diff --git a/bin/pt-index-usage b/bin/pt-index-usage index 185c56ee..9531b88a 100755 --- a/bin/pt-index-usage +++ b/bin/pt-index-usage @@ -29,7 +29,6 @@ BEGIN { ExplainAnalyzer IndexUsage Progress - VersionCheck HTTPMicro Pingback )); @@ -45,7 +44,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -2713,14 +2712,25 @@ sub parse_event { if ( !$found_arg && $pos == $len ) { PTDEBUG && _d("Did not find arg, looking for special cases"); - local $INPUT_RECORD_SEPARATOR = ";\n"; + local $INPUT_RECORD_SEPARATOR = ";\n"; # get next line if ( defined(my $l = $next_event->()) ) { - chomp $l; - $l =~ s/^\s+//; - PTDEBUG && _d("Found admin statement", $l); - push @properties, 'cmd', 'Admin', 'arg', $l; - push @properties, 'bytes', length($properties[-1]); - $found_arg++; + if ( $l =~ /^\s*[A-Z][a-z_]+: / ) { + PTDEBUG && _d("Found NULL query before", $l); + local $INPUT_RECORD_SEPARATOR = ";\n#"; + my $rest_of_event = $next_event->(); + push @{$self->{pending}}, $l . $rest_of_event; + push @properties, 'cmd', 'Query', 'arg', '/* No query */'; + push @properties, 'bytes', 0; + $found_arg++; + } + else { + chomp $l; + $l =~ s/^\s+//; + PTDEBUG && _d("Found admin statement", $l); + push @properties, 'cmd', 'Admin', 'arg', $l; + push @properties, 'bytes', length($properties[-1]); + $found_arg++; + } } else { PTDEBUG && _d("I can't figure out what to do with this line"); @@ -2990,7 +3000,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); @@ -3200,24 +3210,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -3349,6 +3361,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -4420,61 +4435,6 @@ sub fingerprint { my ($explain) = @args{@required_args}; } -sub sparkline { - my ( $self, %args ) = @_; - my @required_args = qw(explain); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my ($explain) = @args{@required_args}; - PTDEBUG && _d("Making sparkline for", Dumper($explain)); - - my $access_code = { - 'ALL' => 'a', - 'const' => 'c', - 'eq_ref' => 'e', - 'fulltext' => 'f', - 'index' => 'i', - 'index_merge' => 'm', - 'range' => 'n', - 'ref_or_null' => 'o', - 'ref' => 'r', - 'system' => 's', - 'unique_subquery' => 'u', - }; - - my $sparkline = ''; - my ($T, $F); # Using temporary, Using filesort - - foreach my $tbl ( @$explain ) { - my $code; - if ( defined $tbl->{type} ) { - $code = $access_code->{$tbl->{type}} || "?"; - $code = uc $code if $tbl->{Extra}->{'Using index'}; - } - else { - $code = '-' - }; - $sparkline .= $code; - - $T = 1 if $tbl->{Extra}->{'Using temporary'}; - $F = 1 if $tbl->{Extra}->{'Using filesort'}; - } - - if ( $T || $F ) { - if ( $explain->[-1]->{Extra}->{'Using temporary'} - || $explain->[-1]->{Extra}->{'Using filesort'} ) { - $sparkline .= ">" . ($T ? "T" : "") . ($F ? "F" : ""); - } - else { - $sparkline = ($T ? "T" : "") . ($F ? "F" : "") . ">$sparkline"; - } - } - - PTDEBUG && _d("sparkline:", $sparkline); - return $sparkline; -} - sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -4866,300 +4826,6 @@ sub _d { # End Progress package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -5849,7 +5515,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -5925,10 +5590,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -5939,13 +5603,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -5975,7 +5639,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -6158,6 +5822,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -7450,8 +7358,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2010-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -7469,6 +7377,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-index-usage 2.1.7 +pt-index-usage 2.1.8 =cut diff --git a/bin/pt-ioprofile b/bin/pt-ioprofile index d97f6040..f73b97ef 100755 --- a/bin/pt-ioprofile +++ b/bin/pt-ioprofile @@ -20,23 +20,32 @@ PTFUNCNAME="" PTDEBUG="${PTDEBUG:-""}" EXIT_STATUS=0 -log() { - TS=$(date +%F-%T | tr ':-' '_'); +ts() { + TS=$(date +%F-%T | tr ':-' '_') echo "$TS $*" } +info() { + [ ${OPT_VERBOSE:-3} -ge 3 ] && ts "$*" +} + +log() { + [ ${OPT_VERBOSE:-3} -ge 2 ] && ts "$*" +} + warn() { - log "$*" >&2 + [ ${OPT_VERBOSE:-3} -ge 1 ] && ts "$*" >&2 EXIT_STATUS=1 } die() { - warn "$*" + ts "$*" >&2 + EXIT_STATUS=1 exit 1 } _d () { - [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(log "$*")" >&2 + [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(ts "$*")" >&2 } # ########################################################################### @@ -69,7 +78,7 @@ PO_DIR="" # Directory with program option spec files usage() { local file="$1" - local usage=$(grep '^Usage: ' "$file") + local usage="$(grep '^Usage: ' "$file")" echo $usage echo echo "For more information, 'man $TOOL' or 'perldoc $file'." @@ -861,7 +870,7 @@ main() { # Execute the program if it was not included from another file. # This makes it possible to include without executing, and thus test. if [ "${0##*/}" = "$TOOL" ] \ - || [ "${0##*/}" = "bash" -a "$_" = "$0" ]; then + || [ "${0##*/}" = "bash" -a "${_:-""}" = "$0" ]; then # Parse command line options. We must do this first so we can # see if --daemonize was specified. @@ -1084,8 +1093,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2010-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -1103,7 +1112,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-ioprofile 2.1.7 +pt-ioprofile 2.1.8 =cut diff --git a/bin/pt-kill b/bin/pt-kill index 600705db..cee09ce3 100755 --- a/bin/pt-kill +++ b/bin/pt-kill @@ -15,7 +15,11 @@ BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit OptionParser - Mo + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo DSNParser Daemon Transformers @@ -27,7 +31,6 @@ BEGIN { QueryRewriter Retry Cxn - VersionCheck HTTPMicro Pingback )); @@ -43,7 +46,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -1077,18 +1080,24 @@ if ( PTDEBUG ) { # ########################################################################### # ########################################################################### -# Mo package +# Lmo::Utils package # This package is a copy without comments from the original. The original # with comments and its test file can be found in the Bazaar repository at, -# lib/Mo.pm -# t/lib/Mo.t +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t # See https://launchpad.net/percona-toolkit for more information. # ########################################################################### { +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} { no strict 'refs'; @@ -1101,6 +1110,194 @@ our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. } } +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + use strict; use warnings qw( FATAL all ); @@ -1122,240 +1319,277 @@ our %TYPES = ( } qw(Array Code Hash Regexp Glob Scalar) ); -our %metadata_for; -{ - package Mo::Object; +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; } - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; } - else { - $ref = { @_ }; - } - return $ref; + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); } } +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + my %export_for; -sub Mo::import { - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); +sub import { + warnings->import(qw(FATAL all)); + strict->import(); - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; } - } - return if $exports{M}; + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; + goto &$original_method + }; + } - $metadata_for{$caller}{$attribute} = (); - - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) } - }, - %exports, - ); + goto &$original_method; + } + } - $export_for{$caller} = [ keys %exports ]; + _install_coderef "${caller}::$attribute" => $method; - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } } sub _has_handles { @@ -1377,8 +1611,8 @@ sub _has_handles { $kv = { map { $_, $_ } grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } keys %{ _stash_for $target_class } }; } @@ -1404,80 +1638,32 @@ sub _has_handles { } } -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $inner_types = _nested_constraints($1, $2); - } - else { - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - return 1 if ! defined($value); - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - sub _set_package_isa { my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; } sub _set_inherited_metadata { my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); my $linearized_isa = mro::get_linear_isa($class); my %new_metadata; for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); %new_metadata = ( %new_metadata, - %{ $metadata_for{$isa_class} || {} }, + %$isa_metadata, ); } - $metadata_for{$class} = \%new_metadata; + %$class_metadata = %new_metadata; } sub unimport { my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); } sub Dumper { @@ -1520,11 +1706,21 @@ BEGIN { } } +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + } 1; } # ########################################################################### -# End Mo package +# End Lmo package # ########################################################################### # ########################################################################### @@ -2126,24 +2322,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -2275,6 +2473,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -2675,7 +2876,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); @@ -4847,300 +5048,6 @@ sub _d { # End Cxn package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -5830,7 +5737,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -5906,10 +5812,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -5920,13 +5825,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -5956,7 +5861,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -6139,6 +6044,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -7767,8 +7916,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2009-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2009-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -7786,6 +7935,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-kill 2.1.7 +pt-kill 2.1.8 =cut diff --git a/bin/pt-mext b/bin/pt-mext index 9a1d1779..34222b78 100755 --- a/bin/pt-mext +++ b/bin/pt-mext @@ -263,8 +263,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2010 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -282,7 +282,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-mext 2.1.7 +pt-mext 2.1.8 =cut diff --git a/bin/pt-mysql-summary b/bin/pt-mysql-summary index 3809408d..8691b59f 100755 --- a/bin/pt-mysql-summary +++ b/bin/pt-mysql-summary @@ -22,23 +22,32 @@ PTFUNCNAME="" PTDEBUG="${PTDEBUG:-""}" EXIT_STATUS=0 -log() { - TS=$(date +%F-%T | tr ':-' '_'); +ts() { + TS=$(date +%F-%T | tr ':-' '_') echo "$TS $*" } +info() { + [ ${OPT_VERBOSE:-3} -ge 3 ] && ts "$*" +} + +log() { + [ ${OPT_VERBOSE:-3} -ge 2 ] && ts "$*" +} + warn() { - log "$*" >&2 + [ ${OPT_VERBOSE:-3} -ge 1 ] && ts "$*" >&2 EXIT_STATUS=1 } die() { - warn "$*" + ts "$*" >&2 + EXIT_STATUS=1 exit 1 } _d () { - [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(log "$*")" >&2 + [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(ts "$*")" >&2 } # ########################################################################### @@ -2412,7 +2421,7 @@ main() { # Execute the program if it was not included from another file. # This makes it possible to include without executing, and thus test. if [ "${0##*/}" = "$TOOL" ] \ - || [ "${0##*/}" = "bash" -a "$_" = "$0" ]; then + || [ "${0##*/}" = "bash" -a "${_:-""}" = "$0" ]; then # Set up temporary dir. mk_tmpdir @@ -2983,8 +2992,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2010-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -3002,7 +3011,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-mysql-summary 2.1.7 +pt-mysql-summary 2.1.8 =cut diff --git a/bin/pt-online-schema-change b/bin/pt-online-schema-change index d3120b26..53eba275 100755 --- a/bin/pt-online-schema-change +++ b/bin/pt-online-schema-change @@ -15,7 +15,11 @@ BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit OptionParser - Mo + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo VersionParser DSNParser Daemon @@ -34,7 +38,6 @@ BEGIN { Transformers CleanupTask IndexLength - VersionCheck HTTPMicro Pingback Percona::XtraDB::Cluster @@ -51,7 +54,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -1084,19 +1087,26 @@ if ( PTDEBUG ) { # End OptionParser package # ########################################################################### + # ########################################################################### -# Mo package +# Lmo::Utils package # This package is a copy without comments from the original. The original # with comments and its test file can be found in the Bazaar repository at, -# lib/Mo.pm -# t/lib/Mo.t +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t # See https://launchpad.net/percona-toolkit for more information. # ########################################################################### { +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} { no strict 'refs'; @@ -1109,6 +1119,194 @@ our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. } } +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + use strict; use warnings qw( FATAL all ); @@ -1130,240 +1328,277 @@ our %TYPES = ( } qw(Array Code Hash Regexp Glob Scalar) ); -our %metadata_for; -{ - package Mo::Object; +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; } - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; } - else { - $ref = { @_ }; - } - return $ref; + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); } } +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + my %export_for; -sub Mo::import { - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); +sub import { + warnings->import(qw(FATAL all)); + strict->import(); - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; } - } - return if $exports{M}; + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; + goto &$original_method + }; + } - $metadata_for{$caller}{$attribute} = (); - - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) } - }, - %exports, - ); + goto &$original_method; + } + } - $export_for{$caller} = [ keys %exports ]; + _install_coderef "${caller}::$attribute" => $method; - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } } sub _has_handles { @@ -1385,8 +1620,8 @@ sub _has_handles { $kv = { map { $_, $_ } grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } keys %{ _stash_for $target_class } }; } @@ -1412,80 +1647,32 @@ sub _has_handles { } } -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $inner_types = _nested_constraints($1, $2); - } - else { - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - return 1 if ! defined($value); - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - sub _set_package_isa { my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; } sub _set_inherited_metadata { my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); my $linearized_isa = mro::get_linear_isa($class); my %new_metadata; for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); %new_metadata = ( %new_metadata, - %{ $metadata_for{$isa_class} || {} }, + %$isa_metadata, ); } - $metadata_for{$class} = \%new_metadata; + %$class_metadata = %new_metadata; } sub unimport { my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); } sub Dumper { @@ -1528,11 +1715,21 @@ BEGIN { } } +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + } 1; } # ########################################################################### -# End Mo package +# End Lmo package # ########################################################################### # ########################################################################### @@ -1546,7 +1743,7 @@ BEGIN { { package VersionParser; -use Mo; +use Lmo; use Scalar::Util qw(blessed); use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -1722,7 +1919,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } -no Mo; +no Lmo; 1; } # ########################################################################### @@ -2319,8 +2516,7 @@ sub _d { { package ReportFormatter; -use strict; -use warnings FATAL => 'all'; +use Lmo; use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -2330,40 +2526,102 @@ use POSIX qw(ceil); eval { require Term::ReadKey }; my $have_term = $EVAL_ERROR ? 0 : 1; -sub new { - my ( $class, %args ) = @_; - my @required_args = qw(); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless $args{$arg}; - } - my $self = { - underline_header => 1, - line_prefix => '# ', - line_width => 78, - column_spacing => ' ', - extend_right => 0, - truncate_line_mark => '...', - column_errors => 'warn', - truncate_header_side => 'left', - strip_whitespace => 1, - %args, # args above can be overriden, args below cannot - n_cols => 0, - }; - if ( ($self->{line_width} || '') eq 'auto' ) { +has underline_header => ( + is => 'ro', + isa => 'Bool', + default => sub { 1 }, +); +has line_prefix => ( + is => 'ro', + isa => 'Str', + default => sub { '# ' }, +); +has line_width => ( + is => 'ro', + isa => 'Int', + default => sub { 78 }, +); +has column_spacing => ( + is => 'ro', + isa => 'Str', + default => sub { ' ' }, +); +has extend_right => ( + is => 'ro', + isa => 'Bool', + default => sub { '' }, +); +has truncate_line_mark => ( + is => 'ro', + isa => 'Str', + default => sub { '...' }, +); +has column_errors => ( + is => 'ro', + isa => 'Str', + default => sub { 'warn' }, +); +has truncate_header_side => ( + is => 'ro', + isa => 'Str', + default => sub { 'left' }, +); +has strip_whitespace => ( + is => 'ro', + isa => 'Bool', + default => sub { 1 }, +); +has title => ( + is => 'rw', + isa => 'Str', + predicate => 'has_title', +); + + +has n_cols => ( + is => 'rw', + isa => 'Int', + default => sub { 0 }, + init_arg => undef, +); + +has cols => ( + is => 'ro', + isa => 'ArrayRef', + init_arg => undef, + default => sub { [] }, + clearer => 'clear_cols', +); + +has lines => ( + is => 'ro', + isa => 'ArrayRef', + init_arg => undef, + default => sub { [] }, + clearer => 'clear_lines', +); + +has truncate_headers => ( + is => 'rw', + isa => 'Bool', + default => sub { undef }, + init_arg => undef, + clearer => 'clear_truncate_headers', +); + +sub BUILDARGS { + my $class = shift; + my $args = $class->SUPER::BUILDARGS(@_); + + if ( ($args->{line_width} || '') eq 'auto' ) { die "Cannot auto-detect line width because the Term::ReadKey module " . "is not installed" unless $have_term; - ($self->{line_width}) = GetTerminalSize(); + ($args->{line_width}) = GetTerminalSize(); + PTDEBUG && _d('Line width:', $args->{line_width}); } - PTDEBUG && _d('Line width:', $self->{line_width}); - return bless $self, $class; -} - -sub set_title { - my ( $self, $title ) = @_; - $self->{title} = $title; - return; + return $args; } sub set_columns { @@ -2379,7 +2637,7 @@ sub set_columns { die "Column does not have a name" unless defined $col_name; if ( $col->{width} ) { - $col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width}); + $col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width()); PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =', $col->{width_pct}, '%'); } @@ -2406,10 +2664,10 @@ sub set_columns { $col->{right_most} = 1 if $i == $#cols; - push @{$self->{cols}}, $col; + push @{$self->cols}, $col; } - $self->{n_cols} = scalar @cols; + $self->n_cols( scalar @cols ); if ( ($used_width || 0) > 100 ) { die "Total width_pct for all columns is >100%"; @@ -2419,15 +2677,15 @@ sub set_columns { my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols); PTDEBUG && _d('Line width left:', (100-$used_width), '%;', 'each auto width col:', $wid_per_col, '%'); - map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols; + map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols; } - $min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing}; + $min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing(); PTDEBUG && _d('min header width:', $min_hdr_wid); - if ( $min_hdr_wid > $self->{line_width} ) { + if ( $min_hdr_wid > $self->line_width() ) { PTDEBUG && _d('Will truncate headers because min header width', - $min_hdr_wid, '> line width', $self->{line_width}); - $self->{truncate_headers} = 1; + $min_hdr_wid, '> line width', $self->line_width()); + $self->truncate_headers(1); } return; @@ -2436,14 +2694,14 @@ sub set_columns { sub add_line { my ( $self, @vals ) = @_; my $n_vals = scalar @vals; - if ( $n_vals != $self->{n_cols} ) { + if ( $n_vals != $self->n_cols() ) { $self->_column_error("Number of values $n_vals does not match " - . "number of columns $self->{n_cols}"); + . "number of columns " . $self->n_cols()); } for my $i ( 0..($n_vals-1) ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value}; - if ( $self->{strip_whitespace} ) { + if ( $self->strip_whitespace() ) { $val =~ s/^\s+//g; $val =~ s/\s+$//; $vals[$i] = $val; @@ -2452,7 +2710,7 @@ sub add_line { $col->{min_val} = min($width, ($col->{min_val} || $width)); $col->{max_val} = max($width, ($col->{max_val} || $width)); } - push @{$self->{lines}}, \@vals; + push @{$self->lines}, \@vals; return; } @@ -2460,26 +2718,28 @@ sub get_report { my ( $self, %args ) = @_; $self->_calculate_column_widths(); - $self->_truncate_headers() if $self->{truncate_headers}; + if ( $self->truncate_headers() ) { + $self->_truncate_headers(); + } $self->_truncate_line_values(%args); my @col_fmts = $self->_make_column_formats(); - my $fmt = ($self->{line_prefix} || '') - . join($self->{column_spacing}, @col_fmts); + my $fmt = $self->line_prefix() + . join($self->column_spacing(), @col_fmts); PTDEBUG && _d('Format:', $fmt); (my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g; my @lines; - push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title}; + push @lines, $self->line_prefix() . $self->title() if $self->has_title(); push @lines, $self->_truncate_line( - sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}), + sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}), strip => 1, mark => '', ); - if ( $self->{underline_header} ) { - my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}}; + if ( $self->underline_header() ) { + my @underlines = map { '=' x $_->{print_width} } @{$self->cols}; push @lines, $self->_truncate_line( sprintf($fmt, map { $_ || '' } @underlines), mark => '', @@ -2490,19 +2750,23 @@ sub get_report { my $vals = $_; my $i = 0; my @vals = map { - my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value}; + my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value}; $val = '' if !defined $val; $val =~ s/\n/ /g; $val; } @$vals; my $line = sprintf($fmt, @vals); - if ( $self->{extend_right} ) { + if ( $self->extend_right() ) { $line; } else { $self->_truncate_line($line); } - } @{$self->{lines}}; + } @{$self->lines}; + + $self->clear_cols(); + $self->clear_lines(); + $self->clear_truncate_headers(); return join("\n", @lines) . "\n"; } @@ -2510,7 +2774,7 @@ sub get_report { sub truncate_value { my ( $self, $col, $val, $width, $side ) = @_; return $val if length $val <= $width; - return $val if $col->{right_most} && $self->{extend_right}; + return $val if $col->{right_most} && $self->extend_right(); $side ||= $col->{truncate_side}; my $mark = $col->{truncate_mark}; if ( $side eq 'right' ) { @@ -2530,8 +2794,8 @@ sub _calculate_column_widths { my ( $self ) = @_; my $extra_space = 0; - foreach my $col ( @{$self->{cols}} ) { - my $print_width = int($self->{line_width} * ($col->{width_pct} / 100)); + foreach my $col ( @{$self->cols} ) { + my $print_width = int($self->line_width() * ($col->{width_pct} / 100)); PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct}, 'char width:', $print_width, @@ -2555,7 +2819,7 @@ sub _calculate_column_widths { PTDEBUG && _d('Extra space:', $extra_space); while ( $extra_space-- ) { - foreach my $col ( @{$self->{cols}} ) { + foreach my $col ( @{$self->cols} ) { if ( $col->{auto_width} && ( $col->{print_width} < $col->{max_val} || $col->{print_width} < $col->{header_width}) @@ -2570,8 +2834,8 @@ sub _calculate_column_widths { sub _truncate_headers { my ( $self, $col ) = @_; - my $side = $self->{truncate_header_side}; - foreach my $col ( @{$self->{cols}} ) { + my $side = $self->truncate_header_side(); + foreach my $col ( @{$self->cols} ) { my $col_name = $col->{name}; my $print_width = $col->{print_width}; next if length $col_name <= $print_width; @@ -2584,10 +2848,10 @@ sub _truncate_headers { sub _truncate_line_values { my ( $self, %args ) = @_; - my $n_vals = $self->{n_cols} - 1; - foreach my $vals ( @{$self->{lines}} ) { + my $n_vals = $self->n_cols() - 1; + foreach my $vals ( @{$self->lines} ) { for my $i ( 0..$n_vals ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value}; my $width = length $val; @@ -2613,9 +2877,9 @@ sub _truncate_line_values { sub _make_column_formats { my ( $self ) = @_; my @col_fmts; - my $n_cols = $self->{n_cols} - 1; + my $n_cols = $self->n_cols() - 1; for my $i ( 0..$n_cols ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $width = $col->{right_most} && !$col->{right_justify} ? '' : $col->{print_width}; @@ -2628,12 +2892,12 @@ sub _make_column_formats { sub _truncate_line { my ( $self, $line, %args ) = @_; - my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark}; + my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark(); if ( $line ) { $line =~ s/\s+$// if $args{strip}; my $len = length($line); - if ( $len > $self->{line_width} ) { - $line = substr($line, 0, $self->{line_width} - length $mark); + if ( $len > $self->line_width() ) { + $line = substr($line, 0, $self->line_width() - length $mark); $line .= $mark if $mark; } } @@ -2643,7 +2907,7 @@ sub _truncate_line { sub _column_error { my ( $self, $err ) = @_; my $msg = "Column error: $err"; - $self->{column_errors} eq 'die' ? die $msg : warn $msg; + $self->column_errors() eq 'die' ? die $msg : warn $msg; return; } @@ -2655,6 +2919,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } +no Lmo; 1; } # ########################################################################### @@ -3270,7 +3535,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); @@ -5686,24 +5951,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -5835,6 +6102,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -6228,300 +6498,6 @@ sub _d { # End IndexLength package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -7211,7 +7187,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -7287,10 +7262,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -7301,13 +7275,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -7337,7 +7311,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -7520,6 +7494,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -7550,7 +7768,7 @@ use warnings FATAL => 'all'; use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; -use Mo; +use Lmo; use Data::Dumper; sub get_cluster_name { @@ -8367,19 +8585,74 @@ sub main { # Find a pk or unique index to use for the delete trigger. can_nibble() # above returns an index, but NibbleIterator will use non-unique indexes, # so we have to do this again here. - my $indexes = $new_tbl->{tbl_struct}->{keys}; # brevity - foreach my $index ( $tp->sort_indexes($new_tbl->{tbl_struct}) ) { - if ( $index eq 'PRIMARY' || $indexes->{$index}->{is_unique} ) { - PTDEBUG && _d('Delete trigger index:', Dumper($index)); - $new_tbl->{del_index} = $index; - last; + { + my $indexes = $new_tbl->{tbl_struct}->{keys}; # brevity + foreach my $index ( $tp->sort_indexes($new_tbl->{tbl_struct}) ) { + if ( $index eq 'PRIMARY' || $indexes->{$index}->{is_unique} ) { + PTDEBUG && _d('Delete trigger new index:', Dumper($index)); + $new_tbl->{del_index} = $index; + last; + } } + PTDEBUG && _d('New table delete index:', $new_tbl->{del_index}); } + + { + my $indexes = $orig_tbl->{tbl_struct}->{keys}; # brevity + foreach my $index ( $tp->sort_indexes($orig_tbl->{tbl_struct}) ) { + if ( $index eq 'PRIMARY' || $indexes->{$index}->{is_unique} ) { + PTDEBUG && _d('Delete trigger orig index:', Dumper($index)); + $orig_tbl->{del_index} = $index; + last; + } + } + PTDEBUG && _d('Orig table delete index:', $orig_tbl->{del_index}); + } + if ( !$new_tbl->{del_index} ) { die "The new table $new_tbl->{name} does not have a PRIMARY KEY " . "or a unique index which is required for the DELETE trigger.\n"; } + # Determine whether to use the new or orig table delete index. + # The new table del index is preferred due to + # https://bugs.launchpad.net/percona-toolkit/+bug/1062324 + # In short, if the chosen del index is re-created with new columns, + # its original columns may be dropped, so just use its new columns. + # But, due to https://bugs.launchpad.net/percona-toolkit/+bug/1103672, + # the chosen del index on the new table may reference columns which + # do not/no longer exist in the orig table, so we check for this + # and, if it's the case, we fall back to using the del index from + # the orig table. + my $del_tbl = $new_tbl; # preferred + my $new_del_index_cols # brevity + = $new_tbl->{tbl_struct}->{keys}->{ $new_tbl->{del_index} }->{cols}; + foreach my $new_del_index_col ( @$new_del_index_cols ) { + if ( !exists $orig_cols->{$new_del_index_col} ) { + if ( !$orig_tbl->{del_index} ) { + die "The new table index $new_tbl->{del_index} would be used " + . "for the DELETE trigger, but it uses column " + . "$new_del_index_col which does not exist in the original " + . "table and the original table does not have a PRIMARY KEY " + . "or a unique index to use for the DELETE trigger.\n"; + } + print "Using original table index $orig_tbl->{del_index} for the " + . "DELETE trigger instead of new table index $new_tbl->{del_index} " + . "because the new table index uses column $new_del_index_col " + . "which does not exist in the original table.\n"; + $del_tbl = $orig_tbl; + last; + } + } + + { + my $del_cols + = $del_tbl->{tbl_struct}->{keys}->{ $del_tbl->{del_index} }->{cols}; + PTDEBUG && _d('Index for delete trigger: table', $del_tbl->{name}, + 'index', $del_tbl->{del_index}, + 'columns', @$del_cols); + } + # ######################################################################## # Step 3: Create the triggers to capture changes on the original table and # apply them to the new table. @@ -8409,6 +8682,7 @@ sub main { create_triggers( orig_tbl => $orig_tbl, new_tbl => $new_tbl, + del_tbl => $del_tbl, columns => \@common_cols, Cxn => $cxn, Quoter => $q, @@ -8927,6 +9201,28 @@ sub check_alter { my $ok = 1; + # ######################################################################## + # Check for DROP PRIMARY KEY. + # ######################################################################## + if ( $alter =~ m/DROP\s+PRIMARY\s+KEY/i ) { + my $msg = "--alter contains 'DROP PRIMARY KEY'. Dropping and " + . "altering the primary key can be dangerous, " + . "especially if the original table does not have other " + . "unique indexes.\n"; + if ( $dry_run ) { + print $msg; + } + else { + $ok = 0; + warn $msg + . "The tool should handle this correctly, but you should " + . "test it first and carefully examine the triggers which " + . "rely on the PRIMARY KEY or a unique index. Specify " + . "--no-check-alter to disable this check and perform the " + . "--alter.\n"; + } + } + # ######################################################################## # Check for renamed columns. # https://bugs.launchpad.net/percona-toolkit/+bug/1068562 @@ -8973,6 +9269,7 @@ sub check_alter { } if ( !$ok ) { + # check_alter.t relies on this output. die "--check-alter failed.\n"; } @@ -9533,11 +9830,11 @@ sub drop_swap { sub create_triggers { my ( %args ) = @_; - my @required_args = qw(orig_tbl new_tbl columns Cxn Quoter OptionParser); + my @required_args = qw(orig_tbl new_tbl del_tbl columns Cxn Quoter OptionParser); foreach my $arg ( @required_args ) { die "I need a $arg argument" unless $args{$arg}; } - my ($orig_tbl, $new_tbl, $cols, $cxn, $q, $o) = @args{@required_args}; + my ($orig_tbl, $new_tbl, $del_tbl, $cols, $cxn, $q, $o) = @args{@required_args}; # This sub works for --dry-run and --execute. With --dry-run it's # only interesting if --print is specified, too; then the user can @@ -9566,8 +9863,8 @@ sub create_triggers { # unique indexes can be nullable. Cols are from the new table and # they may have been renamed my %old_col_for = map { $_->{new} => $_->{old} } @$cols; - my $tbl_struct = $new_tbl->{tbl_struct}; - my $del_index = $new_tbl->{del_index}; + my $tbl_struct = $del_tbl->{tbl_struct}; + my $del_index = $del_tbl->{del_index}; my $del_index_cols = join(" AND ", map { my $new_col = $_; my $old_col = $old_col_for{$new_col} || $new_col; @@ -9695,6 +9992,10 @@ sub exec_nibble { # Ignore this warning because we have purposely set statement-based # replication. 1592 => 1, + # Error: 1062 SQLSTATE: 23000 ( ER_DUP_ENTRY ) + # Message: Duplicate entry '%ld' for key '%s' + # MariaDB 5.5.28+ has this as a warning; See https://bugs.launchpad.net/percona-toolkit/+bug/1099836 + 1062 => 1, ); # Warn once per-table for these error codes if the error message @@ -9769,6 +10070,7 @@ sub exec_nibble { . "Specify --statistics to see a count of all " . "suppressed warnings and errors.\n"; } + warn $err; } } else { @@ -10223,9 +10525,19 @@ In previous versions of the tool, renaming a column with C would lead to that column's data being lost. The tool now parses the alter statement and tries to catch these cases, so the renamed columns should have the same data as the originals. However, the -code that does this is not a full-blown SQL parser, so we recommend that users -run the tool with L<"--dry-run"> and check if it's detecting the renames -correctly. +code that does this is not a full-blown SQL parser, so you should first +run the tool with L<"--dry-run"> and L<"--print"> and verify that it detects +the renamed columns correctly. + +=item DROP PRIMARY KEY + +If L<"--alter"> contain C (case- and space-insensitive), +a warning is printed and the tool exits unless L<"--dry-run"> is specified. +Altering the primary key can be dangerous, but the tool can handle it. +The tool's triggers, particularly the DELETE trigger, are most affected by +altering the primary key because the tool prefers to use the primary key +for its triggers. You should first run the tool with L<"--dry-run"> and +L<"--print"> and verify that the triggers are correct. =back @@ -10830,8 +11142,7 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -10849,6 +11160,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-online-schema-change 2.1.7 +pt-online-schema-change 2.1.8 =cut diff --git a/bin/pt-pmp b/bin/pt-pmp index 405efd7c..549b9cbf 100755 --- a/bin/pt-pmp +++ b/bin/pt-pmp @@ -82,6 +82,7 @@ aggregate_stacktrace() { } else { targ = \$4; + tfile= \$NF; } if ( targ ~ /[<\\(]/ ) { targ = substr(\$0, index(\$0, \" in \") + 4); @@ -126,6 +127,13 @@ aggregate_stacktrace() { } else { fname = targ; + if ( tfile ~ /^\// ) { + last=split(tfile,filen,/\//); + fname = targ \"(\" filen[last] \")\"; + } + else { + fname = targ + } } if ( ${maxlen:-0} == 0 || c < ${maxlen:-0} ) { if (s != \"\" ) { @@ -215,7 +223,7 @@ main() { # Execute the program if it was not included from another file. This makes it # possible to include without executing, and thus test. if [ "${0##*/}" = "$TOOL" ] \ - || [ "${0##*/}" = "bash" -a "$_" = "$0" ]; then + || [ "${0##*/}" = "bash" -a "${_:-""}" = "$0" ]; then mk_tmpdir main "$@" rm_tmpdir @@ -377,8 +385,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2010-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -396,7 +404,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-pmp 2.1.7 +pt-pmp 2.1.8 =cut diff --git a/bin/pt-query-advisor b/bin/pt-query-advisor index a76b0b5a..ece4d479 100755 --- a/bin/pt-query-advisor +++ b/bin/pt-query-advisor @@ -14,6 +14,11 @@ use warnings FATAL => 'all'; BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo DSNParser OptionParser Quoter @@ -30,7 +35,6 @@ BEGIN { SQLParser TableParser ReportFormatter - VersionCheck HTTPMicro Pingback )); @@ -46,7 +50,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -54,6 +58,650 @@ our $VERSION = '2.1.7'; # End Percona::Toolkit package # ########################################################################### +# ########################################################################### +# Lmo::Utils package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + +BEGIN { + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} + +{ + no strict 'refs'; + sub _glob_for { + return \*{shift()} + } + + sub _stash_for { + return \%{ shift() . "::" }; + } +} + +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + + +our %TYPES = ( + Bool => sub { !$_[0] || (defined $_[0] && looks_like_number($_[0]) && $_[0] == 1) }, + Num => sub { defined $_[0] && looks_like_number($_[0]) }, + Int => sub { defined $_[0] && looks_like_number($_[0]) && $_[0] == int($_[0]) }, + Str => sub { defined $_[0] }, + Object => sub { defined $_[0] && blessed($_[0]) }, + FileHandle => sub { local $@; require IO::Handle; fileno($_[0]) && $_[0]->opened }, + + map { + my $type = /R/ ? $_ : uc $_; + $_ . "Ref" => sub { ref $_[0] eq $type } + } qw(Array Code Hash Regexp Glob Scalar) +); + +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} + +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; + + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; + } + + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; + } + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); + } +} + +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + +my %export_for; +sub import { + warnings->import(qw(FATAL all)); + strict->import(); + + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; + } + + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } + + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } + } + goto &$original_method + }; + } + + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) + } + goto &$original_method; + } + } + + _install_coderef "${caller}::$attribute" => $method; + + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } + + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } +} + +sub _has_handles { + my ($caller, $attribute, $args) = @_; + my $handles = $args->{handles}; + + my $ref = ref $handles; + my $kv; + if ( $ref eq ref [] ) { + $kv = { map { $_,$_ } @{$handles} }; + } + elsif ( $ref eq ref {} ) { + $kv = $handles; + } + elsif ( $ref eq ref qr// ) { + Carp::confess("Cannot delegate methods based on a Regexp without a type constraint (isa)") + unless $args->{isa}; + my $target_class = $args->{isa}; + $kv = { + map { $_, $_ } + grep { $_ =~ $handles } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } + keys %{ _stash_for $target_class } + }; + } + else { + Carp::confess("handles for $ref not yet implemented"); + } + + while ( my ($method, $target) = each %{$kv} ) { + my $name = _glob_for "${caller}::$method"; + Carp::confess("You cannot overwrite a locally defined method ($method) with a delegation") + if defined &$name; + + my ($target, @curried_args) = ref($target) ? @$target : $target; + *$name = sub { + my $self = shift; + my $delegate_to = $self->$attribute(); + my $error = "Cannot delegate $method to $target because the value of $attribute"; + Carp::confess("$error is not defined") unless $delegate_to; + Carp::confess("$error is not an object (got '$delegate_to')") + unless Scalar::Util::blessed($delegate_to) || (!ref($delegate_to) && $delegate_to->can($target)); + return $delegate_to->$target(@curried_args, @_); + } + } +} + +sub _set_package_isa { + my ($package, @new_isa) = @_; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; +} + +sub _set_inherited_metadata { + my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); + my $linearized_isa = mro::get_linear_isa($class); + my %new_metadata; + + for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); + %new_metadata = ( + %new_metadata, + %$isa_metadata, + ); + } + %$class_metadata = %new_metadata; +} + +sub unimport { + my $caller = scalar caller(); + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); +} + +sub Dumper { + require Data::Dumper; + local $Data::Dumper::Indent = 0; + local $Data::Dumper::Sortkeys = 0; + local $Data::Dumper::Quotekeys = 0; + local $Data::Dumper::Terse = 1; + + Data::Dumper::Dumper(@_) +} + +BEGIN { + if ($] >= 5.010) { + { local $@; require mro; } + } + else { + local $@; + eval { + require MRO::Compat; + } or do { + *mro::get_linear_isa = *mro::get_linear_isa_dfs = sub { + no strict 'refs'; + + my $classname = shift; + + my @lin = ($classname); + my %stored; + foreach my $parent (@{"$classname\::ISA"}) { + my $plin = mro::get_linear_isa_dfs($parent); + foreach (@$plin) { + next if exists $stored{$_}; + push(@lin, $_); + $stored{$_} = 1; + } + } + return \@lin; + }; + } + } +} + +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + +} +1; +} +# ########################################################################### +# End Lmo package +# ########################################################################### + # ########################################################################### # DSNParser package # This package is a copy without comments from the original. The original @@ -1727,14 +2375,25 @@ sub parse_event { if ( !$found_arg && $pos == $len ) { PTDEBUG && _d("Did not find arg, looking for special cases"); - local $INPUT_RECORD_SEPARATOR = ";\n"; + local $INPUT_RECORD_SEPARATOR = ";\n"; # get next line if ( defined(my $l = $next_event->()) ) { - chomp $l; - $l =~ s/^\s+//; - PTDEBUG && _d("Found admin statement", $l); - push @properties, 'cmd', 'Admin', 'arg', $l; - push @properties, 'bytes', length($properties[-1]); - $found_arg++; + if ( $l =~ /^\s*[A-Z][a-z_]+: / ) { + PTDEBUG && _d("Found NULL query before", $l); + local $INPUT_RECORD_SEPARATOR = ";\n#"; + my $rest_of_event = $next_event->(); + push @{$self->{pending}}, $l . $rest_of_event; + push @properties, 'cmd', 'Query', 'arg', '/* No query */'; + push @properties, 'bytes', 0; + $found_arg++; + } + else { + chomp $l; + $l =~ s/^\s+//; + PTDEBUG && _d("Found admin statement", $l); + push @properties, 'cmd', 'Admin', 'arg', $l; + push @properties, 'bytes', length($properties[-1]); + $found_arg++; + } } else { PTDEBUG && _d("I can't figure out what to do with this line"); @@ -1890,7 +2549,8 @@ sub parse_event { $cmd = $arg; } else { - my ($user, undef, $db) = $arg =~ /(\S+)/g; + my ($user) = $arg =~ m/(\S+)/; + my ($db) = $arg =~ m/on (\S+)/; my $host; ($user, $host) = split(/@/, $user); PTDEBUG && _d('Connect', $user, '@', $host, 'on', $db); @@ -2758,24 +3418,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -2907,6 +3569,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -5505,7 +6170,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); @@ -5706,8 +6371,7 @@ sub _d { { package ReportFormatter; -use strict; -use warnings FATAL => 'all'; +use Lmo; use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -5717,40 +6381,102 @@ use POSIX qw(ceil); eval { require Term::ReadKey }; my $have_term = $EVAL_ERROR ? 0 : 1; -sub new { - my ( $class, %args ) = @_; - my @required_args = qw(); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless $args{$arg}; - } - my $self = { - underline_header => 1, - line_prefix => '# ', - line_width => 78, - column_spacing => ' ', - extend_right => 0, - truncate_line_mark => '...', - column_errors => 'warn', - truncate_header_side => 'left', - strip_whitespace => 1, - %args, # args above can be overriden, args below cannot - n_cols => 0, - }; - if ( ($self->{line_width} || '') eq 'auto' ) { +has underline_header => ( + is => 'ro', + isa => 'Bool', + default => sub { 1 }, +); +has line_prefix => ( + is => 'ro', + isa => 'Str', + default => sub { '# ' }, +); +has line_width => ( + is => 'ro', + isa => 'Int', + default => sub { 78 }, +); +has column_spacing => ( + is => 'ro', + isa => 'Str', + default => sub { ' ' }, +); +has extend_right => ( + is => 'ro', + isa => 'Bool', + default => sub { '' }, +); +has truncate_line_mark => ( + is => 'ro', + isa => 'Str', + default => sub { '...' }, +); +has column_errors => ( + is => 'ro', + isa => 'Str', + default => sub { 'warn' }, +); +has truncate_header_side => ( + is => 'ro', + isa => 'Str', + default => sub { 'left' }, +); +has strip_whitespace => ( + is => 'ro', + isa => 'Bool', + default => sub { 1 }, +); +has title => ( + is => 'rw', + isa => 'Str', + predicate => 'has_title', +); + + +has n_cols => ( + is => 'rw', + isa => 'Int', + default => sub { 0 }, + init_arg => undef, +); + +has cols => ( + is => 'ro', + isa => 'ArrayRef', + init_arg => undef, + default => sub { [] }, + clearer => 'clear_cols', +); + +has lines => ( + is => 'ro', + isa => 'ArrayRef', + init_arg => undef, + default => sub { [] }, + clearer => 'clear_lines', +); + +has truncate_headers => ( + is => 'rw', + isa => 'Bool', + default => sub { undef }, + init_arg => undef, + clearer => 'clear_truncate_headers', +); + +sub BUILDARGS { + my $class = shift; + my $args = $class->SUPER::BUILDARGS(@_); + + if ( ($args->{line_width} || '') eq 'auto' ) { die "Cannot auto-detect line width because the Term::ReadKey module " . "is not installed" unless $have_term; - ($self->{line_width}) = GetTerminalSize(); + ($args->{line_width}) = GetTerminalSize(); + PTDEBUG && _d('Line width:', $args->{line_width}); } - PTDEBUG && _d('Line width:', $self->{line_width}); - return bless $self, $class; -} - -sub set_title { - my ( $self, $title ) = @_; - $self->{title} = $title; - return; + return $args; } sub set_columns { @@ -5766,7 +6492,7 @@ sub set_columns { die "Column does not have a name" unless defined $col_name; if ( $col->{width} ) { - $col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width}); + $col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width()); PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =', $col->{width_pct}, '%'); } @@ -5793,10 +6519,10 @@ sub set_columns { $col->{right_most} = 1 if $i == $#cols; - push @{$self->{cols}}, $col; + push @{$self->cols}, $col; } - $self->{n_cols} = scalar @cols; + $self->n_cols( scalar @cols ); if ( ($used_width || 0) > 100 ) { die "Total width_pct for all columns is >100%"; @@ -5806,15 +6532,15 @@ sub set_columns { my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols); PTDEBUG && _d('Line width left:', (100-$used_width), '%;', 'each auto width col:', $wid_per_col, '%'); - map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols; + map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols; } - $min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing}; + $min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing(); PTDEBUG && _d('min header width:', $min_hdr_wid); - if ( $min_hdr_wid > $self->{line_width} ) { + if ( $min_hdr_wid > $self->line_width() ) { PTDEBUG && _d('Will truncate headers because min header width', - $min_hdr_wid, '> line width', $self->{line_width}); - $self->{truncate_headers} = 1; + $min_hdr_wid, '> line width', $self->line_width()); + $self->truncate_headers(1); } return; @@ -5823,14 +6549,14 @@ sub set_columns { sub add_line { my ( $self, @vals ) = @_; my $n_vals = scalar @vals; - if ( $n_vals != $self->{n_cols} ) { + if ( $n_vals != $self->n_cols() ) { $self->_column_error("Number of values $n_vals does not match " - . "number of columns $self->{n_cols}"); + . "number of columns " . $self->n_cols()); } for my $i ( 0..($n_vals-1) ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value}; - if ( $self->{strip_whitespace} ) { + if ( $self->strip_whitespace() ) { $val =~ s/^\s+//g; $val =~ s/\s+$//; $vals[$i] = $val; @@ -5839,7 +6565,7 @@ sub add_line { $col->{min_val} = min($width, ($col->{min_val} || $width)); $col->{max_val} = max($width, ($col->{max_val} || $width)); } - push @{$self->{lines}}, \@vals; + push @{$self->lines}, \@vals; return; } @@ -5847,26 +6573,28 @@ sub get_report { my ( $self, %args ) = @_; $self->_calculate_column_widths(); - $self->_truncate_headers() if $self->{truncate_headers}; + if ( $self->truncate_headers() ) { + $self->_truncate_headers(); + } $self->_truncate_line_values(%args); my @col_fmts = $self->_make_column_formats(); - my $fmt = ($self->{line_prefix} || '') - . join($self->{column_spacing}, @col_fmts); + my $fmt = $self->line_prefix() + . join($self->column_spacing(), @col_fmts); PTDEBUG && _d('Format:', $fmt); (my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g; my @lines; - push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title}; + push @lines, $self->line_prefix() . $self->title() if $self->has_title(); push @lines, $self->_truncate_line( - sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}), + sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}), strip => 1, mark => '', ); - if ( $self->{underline_header} ) { - my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}}; + if ( $self->underline_header() ) { + my @underlines = map { '=' x $_->{print_width} } @{$self->cols}; push @lines, $self->_truncate_line( sprintf($fmt, map { $_ || '' } @underlines), mark => '', @@ -5877,19 +6605,23 @@ sub get_report { my $vals = $_; my $i = 0; my @vals = map { - my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value}; + my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value}; $val = '' if !defined $val; $val =~ s/\n/ /g; $val; } @$vals; my $line = sprintf($fmt, @vals); - if ( $self->{extend_right} ) { + if ( $self->extend_right() ) { $line; } else { $self->_truncate_line($line); } - } @{$self->{lines}}; + } @{$self->lines}; + + $self->clear_cols(); + $self->clear_lines(); + $self->clear_truncate_headers(); return join("\n", @lines) . "\n"; } @@ -5897,7 +6629,7 @@ sub get_report { sub truncate_value { my ( $self, $col, $val, $width, $side ) = @_; return $val if length $val <= $width; - return $val if $col->{right_most} && $self->{extend_right}; + return $val if $col->{right_most} && $self->extend_right(); $side ||= $col->{truncate_side}; my $mark = $col->{truncate_mark}; if ( $side eq 'right' ) { @@ -5917,8 +6649,8 @@ sub _calculate_column_widths { my ( $self ) = @_; my $extra_space = 0; - foreach my $col ( @{$self->{cols}} ) { - my $print_width = int($self->{line_width} * ($col->{width_pct} / 100)); + foreach my $col ( @{$self->cols} ) { + my $print_width = int($self->line_width() * ($col->{width_pct} / 100)); PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct}, 'char width:', $print_width, @@ -5942,7 +6674,7 @@ sub _calculate_column_widths { PTDEBUG && _d('Extra space:', $extra_space); while ( $extra_space-- ) { - foreach my $col ( @{$self->{cols}} ) { + foreach my $col ( @{$self->cols} ) { if ( $col->{auto_width} && ( $col->{print_width} < $col->{max_val} || $col->{print_width} < $col->{header_width}) @@ -5957,8 +6689,8 @@ sub _calculate_column_widths { sub _truncate_headers { my ( $self, $col ) = @_; - my $side = $self->{truncate_header_side}; - foreach my $col ( @{$self->{cols}} ) { + my $side = $self->truncate_header_side(); + foreach my $col ( @{$self->cols} ) { my $col_name = $col->{name}; my $print_width = $col->{print_width}; next if length $col_name <= $print_width; @@ -5971,10 +6703,10 @@ sub _truncate_headers { sub _truncate_line_values { my ( $self, %args ) = @_; - my $n_vals = $self->{n_cols} - 1; - foreach my $vals ( @{$self->{lines}} ) { + my $n_vals = $self->n_cols() - 1; + foreach my $vals ( @{$self->lines} ) { for my $i ( 0..$n_vals ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value}; my $width = length $val; @@ -6000,9 +6732,9 @@ sub _truncate_line_values { sub _make_column_formats { my ( $self ) = @_; my @col_fmts; - my $n_cols = $self->{n_cols} - 1; + my $n_cols = $self->n_cols() - 1; for my $i ( 0..$n_cols ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $width = $col->{right_most} && !$col->{right_justify} ? '' : $col->{print_width}; @@ -6015,12 +6747,12 @@ sub _make_column_formats { sub _truncate_line { my ( $self, $line, %args ) = @_; - my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark}; + my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark(); if ( $line ) { $line =~ s/\s+$// if $args{strip}; my $len = length($line); - if ( $len > $self->{line_width} ) { - $line = substr($line, 0, $self->{line_width} - length $mark); + if ( $len > $self->line_width() ) { + $line = substr($line, 0, $self->line_width() - length $mark); $line .= $mark if $mark; } } @@ -6030,7 +6762,7 @@ sub _truncate_line { sub _column_error { my ( $self, $err ) = @_; my $msg = "Column error: $err"; - $self->{column_errors} eq 'die' ? die $msg : warn $msg; + $self->column_errors() eq 'die' ? die $msg : warn $msg; return; } @@ -6042,306 +6774,13 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } +no Lmo; 1; } # ########################################################################### # End ReportFormatter package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -7031,7 +7470,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -7107,10 +7545,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -7121,13 +7558,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -7157,7 +7594,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -7340,6 +7777,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -7835,7 +8516,7 @@ sub main { long_last_column => 1, extend_right => 1, ); - $profile->set_title("Profile"); + $profile->title("Profile"); $profile->set_columns( { name => 'Query ID', }, { name => 'NOTE', right_justify => 1, }, @@ -8694,8 +9375,7 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2010-2013 Percona Ireland Ltd. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -8713,6 +9393,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-query-advisor 2.1.7 +pt-query-advisor 2.1.8 =cut diff --git a/bin/pt-query-digest b/bin/pt-query-digest index c31c4fbf..7ed101b0 100755 --- a/bin/pt-query-digest +++ b/bin/pt-query-digest @@ -14,6 +14,11 @@ use warnings FATAL => 'all'; BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo DSNParser Quoter OptionParser @@ -29,6 +34,7 @@ BEGIN { EventAggregator ReportFormatter QueryReportFormatter + JSONReportFormatter EventTimeline QueryParser TableParser @@ -41,14 +47,11 @@ BEGIN { RawLogParser ProtocolParser HTTPProtocolParser - ExecutionThrottler MasterSlave Progress FileIterator - ExplainAnalyzer Runtime Pipeline - VersionCheck HTTPMicro Pingback )); @@ -64,7 +67,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -72,6 +75,650 @@ our $VERSION = '2.1.7'; # End Percona::Toolkit package # ########################################################################### +# ########################################################################### +# Lmo::Utils package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + +BEGIN { + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} + +{ + no strict 'refs'; + sub _glob_for { + return \*{shift()} + } + + sub _stash_for { + return \%{ shift() . "::" }; + } +} + +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + + +our %TYPES = ( + Bool => sub { !$_[0] || (defined $_[0] && looks_like_number($_[0]) && $_[0] == 1) }, + Num => sub { defined $_[0] && looks_like_number($_[0]) }, + Int => sub { defined $_[0] && looks_like_number($_[0]) && $_[0] == int($_[0]) }, + Str => sub { defined $_[0] }, + Object => sub { defined $_[0] && blessed($_[0]) }, + FileHandle => sub { local $@; require IO::Handle; fileno($_[0]) && $_[0]->opened }, + + map { + my $type = /R/ ? $_ : uc $_; + $_ . "Ref" => sub { ref $_[0] eq $type } + } qw(Array Code Hash Regexp Glob Scalar) +); + +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} + +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; + + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; + } + + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; + } + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); + } +} + +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + +my %export_for; +sub import { + warnings->import(qw(FATAL all)); + strict->import(); + + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; + } + + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } + + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } + } + goto &$original_method + }; + } + + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) + } + goto &$original_method; + } + } + + _install_coderef "${caller}::$attribute" => $method; + + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } + + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } +} + +sub _has_handles { + my ($caller, $attribute, $args) = @_; + my $handles = $args->{handles}; + + my $ref = ref $handles; + my $kv; + if ( $ref eq ref [] ) { + $kv = { map { $_,$_ } @{$handles} }; + } + elsif ( $ref eq ref {} ) { + $kv = $handles; + } + elsif ( $ref eq ref qr// ) { + Carp::confess("Cannot delegate methods based on a Regexp without a type constraint (isa)") + unless $args->{isa}; + my $target_class = $args->{isa}; + $kv = { + map { $_, $_ } + grep { $_ =~ $handles } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } + keys %{ _stash_for $target_class } + }; + } + else { + Carp::confess("handles for $ref not yet implemented"); + } + + while ( my ($method, $target) = each %{$kv} ) { + my $name = _glob_for "${caller}::$method"; + Carp::confess("You cannot overwrite a locally defined method ($method) with a delegation") + if defined &$name; + + my ($target, @curried_args) = ref($target) ? @$target : $target; + *$name = sub { + my $self = shift; + my $delegate_to = $self->$attribute(); + my $error = "Cannot delegate $method to $target because the value of $attribute"; + Carp::confess("$error is not defined") unless $delegate_to; + Carp::confess("$error is not an object (got '$delegate_to')") + unless Scalar::Util::blessed($delegate_to) || (!ref($delegate_to) && $delegate_to->can($target)); + return $delegate_to->$target(@curried_args, @_); + } + } +} + +sub _set_package_isa { + my ($package, @new_isa) = @_; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; +} + +sub _set_inherited_metadata { + my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); + my $linearized_isa = mro::get_linear_isa($class); + my %new_metadata; + + for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); + %new_metadata = ( + %new_metadata, + %$isa_metadata, + ); + } + %$class_metadata = %new_metadata; +} + +sub unimport { + my $caller = scalar caller(); + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); +} + +sub Dumper { + require Data::Dumper; + local $Data::Dumper::Indent = 0; + local $Data::Dumper::Sortkeys = 0; + local $Data::Dumper::Quotekeys = 0; + local $Data::Dumper::Terse = 1; + + Data::Dumper::Dumper(@_) +} + +BEGIN { + if ($] >= 5.010) { + { local $@; require mro; } + } + else { + local $@; + eval { + require MRO::Compat; + } or do { + *mro::get_linear_isa = *mro::get_linear_isa_dfs = sub { + no strict 'refs'; + + my $classname = shift; + + my @lin = ($classname); + my %stored; + foreach my $parent (@{"$classname\::ISA"}) { + my $plin = mro::get_linear_isa_dfs($parent); + foreach (@$plin) { + next if exists $stored{$_}; + push(@lin, $_); + $stored{$_} = 1; + } + } + return \@lin; + }; + } + } +} + +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + +} +1; +} +# ########################################################################### +# End Lmo package +# ########################################################################### + # ########################################################################### # DSNParser package # This package is a copy without comments from the original. The original @@ -1620,24 +2267,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -1769,6 +2418,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -3129,6 +3781,19 @@ sub parse_event { if ( $packet->{data_len} == 0 ) { PTDEBUG && _d('TCP control:', map { uc $_ } grep { $packet->{$_} } qw(syn ack fin rst)); + if ( $packet->{'fin'} + && ($session->{state} || '') eq 'server_handshake' ) { + PTDEBUG && _d('Client aborted connection'); + my $event = { + cmd => 'Admin', + arg => 'administrator command: Connect', + ts => $packet->{ts}, + }; + $session->{attribs}->{Error_msg} = 'Client closed connection during handshake'; + $event = $self->_make_event($event, $packet, $session); + delete $self->{sessions}->{$session->{client}}; + return $event; + } return; } @@ -3345,7 +4010,8 @@ sub _packet_from_server { } my $event; - if ( $session->{state} eq 'client_auth' ) { + if ( $session->{state} eq 'client_auth' + || $session->{state} eq 'server_handshake' ) { PTDEBUG && _d('Connection failed'); $event = { cmd => 'Admin', @@ -3372,11 +4038,13 @@ sub _packet_from_server { } $event = { - cmd => $com, - arg => $arg, - ts => $packet->{ts}, - Error_no => $error->{errno} ? "#$error->{errno}" : 'none', + cmd => $com, + arg => $arg, + ts => $packet->{ts}, }; + if ( $error->{errno} ) { + $event->{Error_no} = $error->{errno}; + } $session->{attribs}->{Error_msg} = $error->{message}; return $self->_make_event($event, $packet, $session); } @@ -3587,13 +4255,17 @@ sub _make_event { Thread_id => $session->{thread_id}, pos_in_log => $session->{pos_in_log}, Query_time => timestamp_diff($session->{ts}, $packet->{ts}), - Error_no => $event->{Error_no} || 'none', Rows_affected => ($event->{Rows_affected} || 0), Warning_count => ($event->{Warning_count} || 0), No_good_index_used => ($event->{No_good_index_used} ? 'Yes' : 'No'), No_index_used => ($event->{No_index_used} ? 'Yes' : 'No'), }; @{$new_event}{keys %{$session->{attribs}}} = values %{$session->{attribs}}; + foreach my $opt_attrib ( qw(Error_no) ) { + if ( defined $event->{$opt_attrib} ) { + $new_event->{$opt_attrib} = $event->{$opt_attrib}; + } + } PTDEBUG && _d('Properties of event:', Dumper($new_event)); delete $session->{cmd}; @@ -3724,9 +4396,17 @@ sub parse_error_packet { } my $errno = to_num(substr($data, 0, 4)); my $marker = to_string(substr($data, 4, 2)); - return unless $marker eq '#'; - my $sqlstate = to_string(substr($data, 6, 10)); - my $message = to_string(substr($data, 16)); + my $sqlstate = ''; + my $message = ''; + if ( $marker eq '#' ) { + $sqlstate = to_string(substr($data, 6, 10)); + $message = to_string(substr($data, 16)); + } + else { + $marker = ''; + $message = to_string(substr($data, 4)); + } + return unless $message; my $pkt = { errno => $errno, sqlstate => $marker . $sqlstate, @@ -5445,15 +6125,6 @@ sub calculate_statistical_metrics { $classes->{$class}->{$attrib}->{all}, $classes->{$class}->{$attrib} ); - - if ( $args{apdex_t} && $attrib eq 'Query_time' ) { - $class_metrics->{$class}->{$attrib}->{apdex_t} = $args{apdex_t}; - $class_metrics->{$class}->{$attrib}->{apdex} - = $self->calculate_apdex( - t => $args{apdex_t}, - samples => $classes->{$class}->{$attrib}->{all}, - ); - } } } } @@ -5578,9 +6249,6 @@ sub metrics { median => $metrics->{classes}->{$where}->{$attrib}->{median} || 0, pct_95 => $metrics->{classes}->{$where}->{$attrib}->{pct_95} || 0, stddev => $metrics->{classes}->{$where}->{$attrib}->{stddev} || 0, - - apdex_t => $metrics->{classes}->{$where}->{$attrib}->{apdex_t}, - apdex => $metrics->{classes}->{$where}->{$attrib}->{apdex}, }; } @@ -5896,51 +6564,6 @@ sub _deep_copy_attrib_vals { return $copy; } -sub calculate_apdex { - my ( $self, %args ) = @_; - my @required_args = qw(t samples); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless $args{$arg}; - } - my ($t, $samples) = @args{@required_args}; - - if ( $t <= 0 ) { - die "Invalid target threshold (T): $t. T must be greater than zero"; - } - - my $f = 4 * $t; - PTDEBUG && _d("Apdex T =", $t, "F =", $f); - - my $satisfied = 0; - my $tolerating = 0; - my $frustrated = 0; # just for debug output - my $n_samples = 0; - BUCKET: - for my $bucket ( keys %$samples ) { - my $n_responses = $samples->{$bucket}; - my $response_time = $buck_vals[$bucket]; - - if ( $response_time <= $t ) { - $satisfied += $n_responses; - } - elsif ( $response_time <= $f ) { - $tolerating += $n_responses; - } - else { - $frustrated += $n_responses; - } - - $n_samples += $n_responses; - } - - my $apdex = sprintf('%.2f', ($satisfied + ($tolerating / 2)) / $n_samples); - PTDEBUG && _d($n_samples, "samples,", $satisfied, "satisfied,", - $tolerating, "tolerating,", $frustrated, "frustrated, Apdex score:", - $apdex); - - return $apdex; -} - sub _get_value { my ( $self, %args ) = @_; my ($event, $attrib, $alts) = @args{qw(event attribute alternates)}; @@ -5994,8 +6617,7 @@ sub _d { { package ReportFormatter; -use strict; -use warnings FATAL => 'all'; +use Lmo; use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -6005,40 +6627,102 @@ use POSIX qw(ceil); eval { require Term::ReadKey }; my $have_term = $EVAL_ERROR ? 0 : 1; -sub new { - my ( $class, %args ) = @_; - my @required_args = qw(); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless $args{$arg}; - } - my $self = { - underline_header => 1, - line_prefix => '# ', - line_width => 78, - column_spacing => ' ', - extend_right => 0, - truncate_line_mark => '...', - column_errors => 'warn', - truncate_header_side => 'left', - strip_whitespace => 1, - %args, # args above can be overriden, args below cannot - n_cols => 0, - }; - if ( ($self->{line_width} || '') eq 'auto' ) { +has underline_header => ( + is => 'ro', + isa => 'Bool', + default => sub { 1 }, +); +has line_prefix => ( + is => 'ro', + isa => 'Str', + default => sub { '# ' }, +); +has line_width => ( + is => 'ro', + isa => 'Int', + default => sub { 78 }, +); +has column_spacing => ( + is => 'ro', + isa => 'Str', + default => sub { ' ' }, +); +has extend_right => ( + is => 'ro', + isa => 'Bool', + default => sub { '' }, +); +has truncate_line_mark => ( + is => 'ro', + isa => 'Str', + default => sub { '...' }, +); +has column_errors => ( + is => 'ro', + isa => 'Str', + default => sub { 'warn' }, +); +has truncate_header_side => ( + is => 'ro', + isa => 'Str', + default => sub { 'left' }, +); +has strip_whitespace => ( + is => 'ro', + isa => 'Bool', + default => sub { 1 }, +); +has title => ( + is => 'rw', + isa => 'Str', + predicate => 'has_title', +); + + +has n_cols => ( + is => 'rw', + isa => 'Int', + default => sub { 0 }, + init_arg => undef, +); + +has cols => ( + is => 'ro', + isa => 'ArrayRef', + init_arg => undef, + default => sub { [] }, + clearer => 'clear_cols', +); + +has lines => ( + is => 'ro', + isa => 'ArrayRef', + init_arg => undef, + default => sub { [] }, + clearer => 'clear_lines', +); + +has truncate_headers => ( + is => 'rw', + isa => 'Bool', + default => sub { undef }, + init_arg => undef, + clearer => 'clear_truncate_headers', +); + +sub BUILDARGS { + my $class = shift; + my $args = $class->SUPER::BUILDARGS(@_); + + if ( ($args->{line_width} || '') eq 'auto' ) { die "Cannot auto-detect line width because the Term::ReadKey module " . "is not installed" unless $have_term; - ($self->{line_width}) = GetTerminalSize(); + ($args->{line_width}) = GetTerminalSize(); + PTDEBUG && _d('Line width:', $args->{line_width}); } - PTDEBUG && _d('Line width:', $self->{line_width}); - return bless $self, $class; -} - -sub set_title { - my ( $self, $title ) = @_; - $self->{title} = $title; - return; + return $args; } sub set_columns { @@ -6054,7 +6738,7 @@ sub set_columns { die "Column does not have a name" unless defined $col_name; if ( $col->{width} ) { - $col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width}); + $col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width()); PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =', $col->{width_pct}, '%'); } @@ -6081,10 +6765,10 @@ sub set_columns { $col->{right_most} = 1 if $i == $#cols; - push @{$self->{cols}}, $col; + push @{$self->cols}, $col; } - $self->{n_cols} = scalar @cols; + $self->n_cols( scalar @cols ); if ( ($used_width || 0) > 100 ) { die "Total width_pct for all columns is >100%"; @@ -6094,15 +6778,15 @@ sub set_columns { my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols); PTDEBUG && _d('Line width left:', (100-$used_width), '%;', 'each auto width col:', $wid_per_col, '%'); - map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols; + map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols; } - $min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing}; + $min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing(); PTDEBUG && _d('min header width:', $min_hdr_wid); - if ( $min_hdr_wid > $self->{line_width} ) { + if ( $min_hdr_wid > $self->line_width() ) { PTDEBUG && _d('Will truncate headers because min header width', - $min_hdr_wid, '> line width', $self->{line_width}); - $self->{truncate_headers} = 1; + $min_hdr_wid, '> line width', $self->line_width()); + $self->truncate_headers(1); } return; @@ -6111,14 +6795,14 @@ sub set_columns { sub add_line { my ( $self, @vals ) = @_; my $n_vals = scalar @vals; - if ( $n_vals != $self->{n_cols} ) { + if ( $n_vals != $self->n_cols() ) { $self->_column_error("Number of values $n_vals does not match " - . "number of columns $self->{n_cols}"); + . "number of columns " . $self->n_cols()); } for my $i ( 0..($n_vals-1) ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value}; - if ( $self->{strip_whitespace} ) { + if ( $self->strip_whitespace() ) { $val =~ s/^\s+//g; $val =~ s/\s+$//; $vals[$i] = $val; @@ -6127,7 +6811,7 @@ sub add_line { $col->{min_val} = min($width, ($col->{min_val} || $width)); $col->{max_val} = max($width, ($col->{max_val} || $width)); } - push @{$self->{lines}}, \@vals; + push @{$self->lines}, \@vals; return; } @@ -6135,26 +6819,28 @@ sub get_report { my ( $self, %args ) = @_; $self->_calculate_column_widths(); - $self->_truncate_headers() if $self->{truncate_headers}; + if ( $self->truncate_headers() ) { + $self->_truncate_headers(); + } $self->_truncate_line_values(%args); my @col_fmts = $self->_make_column_formats(); - my $fmt = ($self->{line_prefix} || '') - . join($self->{column_spacing}, @col_fmts); + my $fmt = $self->line_prefix() + . join($self->column_spacing(), @col_fmts); PTDEBUG && _d('Format:', $fmt); (my $hdr_fmt = $fmt) =~ s/%([^-])/%-$1/g; my @lines; - push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title}; + push @lines, $self->line_prefix() . $self->title() if $self->has_title(); push @lines, $self->_truncate_line( - sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}), + sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}), strip => 1, mark => '', ); - if ( $self->{underline_header} ) { - my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}}; + if ( $self->underline_header() ) { + my @underlines = map { '=' x $_->{print_width} } @{$self->cols}; push @lines, $self->_truncate_line( sprintf($fmt, map { $_ || '' } @underlines), mark => '', @@ -6165,19 +6851,23 @@ sub get_report { my $vals = $_; my $i = 0; my @vals = map { - my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value}; + my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value}; $val = '' if !defined $val; $val =~ s/\n/ /g; $val; } @$vals; my $line = sprintf($fmt, @vals); - if ( $self->{extend_right} ) { + if ( $self->extend_right() ) { $line; } else { $self->_truncate_line($line); } - } @{$self->{lines}}; + } @{$self->lines}; + + $self->clear_cols(); + $self->clear_lines(); + $self->clear_truncate_headers(); return join("\n", @lines) . "\n"; } @@ -6185,7 +6875,7 @@ sub get_report { sub truncate_value { my ( $self, $col, $val, $width, $side ) = @_; return $val if length $val <= $width; - return $val if $col->{right_most} && $self->{extend_right}; + return $val if $col->{right_most} && $self->extend_right(); $side ||= $col->{truncate_side}; my $mark = $col->{truncate_mark}; if ( $side eq 'right' ) { @@ -6205,8 +6895,8 @@ sub _calculate_column_widths { my ( $self ) = @_; my $extra_space = 0; - foreach my $col ( @{$self->{cols}} ) { - my $print_width = int($self->{line_width} * ($col->{width_pct} / 100)); + foreach my $col ( @{$self->cols} ) { + my $print_width = int($self->line_width() * ($col->{width_pct} / 100)); PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct}, 'char width:', $print_width, @@ -6230,7 +6920,7 @@ sub _calculate_column_widths { PTDEBUG && _d('Extra space:', $extra_space); while ( $extra_space-- ) { - foreach my $col ( @{$self->{cols}} ) { + foreach my $col ( @{$self->cols} ) { if ( $col->{auto_width} && ( $col->{print_width} < $col->{max_val} || $col->{print_width} < $col->{header_width}) @@ -6245,8 +6935,8 @@ sub _calculate_column_widths { sub _truncate_headers { my ( $self, $col ) = @_; - my $side = $self->{truncate_header_side}; - foreach my $col ( @{$self->{cols}} ) { + my $side = $self->truncate_header_side(); + foreach my $col ( @{$self->cols} ) { my $col_name = $col->{name}; my $print_width = $col->{print_width}; next if length $col_name <= $print_width; @@ -6259,10 +6949,10 @@ sub _truncate_headers { sub _truncate_line_values { my ( $self, %args ) = @_; - my $n_vals = $self->{n_cols} - 1; - foreach my $vals ( @{$self->{lines}} ) { + my $n_vals = $self->n_cols() - 1; + foreach my $vals ( @{$self->lines} ) { for my $i ( 0..$n_vals ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value}; my $width = length $val; @@ -6288,9 +6978,9 @@ sub _truncate_line_values { sub _make_column_formats { my ( $self ) = @_; my @col_fmts; - my $n_cols = $self->{n_cols} - 1; + my $n_cols = $self->n_cols() - 1; for my $i ( 0..$n_cols ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $width = $col->{right_most} && !$col->{right_justify} ? '' : $col->{print_width}; @@ -6303,12 +6993,12 @@ sub _make_column_formats { sub _truncate_line { my ( $self, $line, %args ) = @_; - my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark}; + my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark(); if ( $line ) { $line =~ s/\s+$// if $args{strip}; my $len = length($line); - if ( $len > $self->{line_width} ) { - $line = substr($line, 0, $self->{line_width} - length $mark); + if ( $len > $self->line_width() ) { + $line = substr($line, 0, $self->line_width() - length $mark); $line .= $mark if $mark; } } @@ -6318,7 +7008,7 @@ sub _truncate_line { sub _column_error { my ( $self, $err ) = @_; my $msg = "Column error: $err"; - $self->{column_errors} eq 'die' ? die $msg : warn $msg; + $self->column_errors() eq 'die' ? die $msg : warn $msg; return; } @@ -6330,6 +7020,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } +no Lmo; 1; } # ########################################################################### @@ -6347,8 +7038,7 @@ sub _d { { package QueryReportFormatter; -use strict; -use warnings FATAL => 'all'; +use Lmo; use English qw(-no_match_vars); use POSIX qw(floor); @@ -6361,25 +7051,68 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0; use constant LINE_LENGTH => 74; use constant MAX_STRING_LENGTH => 10; -sub new { - my ( $class, %args ) = @_; - foreach my $arg ( qw(OptionParser QueryRewriter Quoter) ) { - die "I need a $arg argument" unless $args{$arg}; +{ local $EVAL_ERROR; eval { require Quoter } }; +{ local $EVAL_ERROR; eval { require ReportFormatter } }; + +has Quoter => ( + is => 'ro', + isa => 'Quoter', + default => sub { Quoter->new() }, +); + +has label_width => ( + is => 'ro', + isa => 'Int', +); + +has global_headers => ( + is => 'ro', + isa => 'ArrayRef', + default => sub { [qw( total min max avg 95% stddev median)] }, +); + +has event_headers => ( + is => 'ro', + isa => 'ArrayRef', + default => sub { [qw(pct total min max avg 95% stddev median)] }, +); + +has ReportFormatter => ( + is => 'ro', + isa => 'ReportFormatter', + builder => '_build_report_formatter', +); + +sub _build_report_formatter { + return ReportFormatter->new( + line_width => LINE_LENGTH, + extend_right => 1, + ); +} + +sub BUILDARGS { + my $class = shift; + my $args = $class->SUPER::BUILDARGS(@_); + + foreach my $arg ( qw(OptionParser QueryRewriter) ) { + die "I need a $arg argument" unless $args->{$arg}; } - my $label_width = $args{label_width} || 12; + my $label_width = $args->{label_width} ||= 12; PTDEBUG && _d('Label width:', $label_width); - my $cheat_width = $label_width + 1; - + my $o = delete $args->{OptionParser}; my $self = { - %args, - label_width => $label_width, + %$args, + options => { + show_all => $o->get('show-all'), + shorten => $o->get('shorten'), + report_all => $o->get('report-all'), + report_histogram => $o->get('report-histogram'), + }, num_format => "# %-${label_width}s %3s %7s %7s %7s %7s %7s %7s %7s", bool_format => "# %-${label_width}s %3d%% yes, %3d%% no", string_format => "# %-${label_width}s %s", - global_headers => [qw( total min max avg 95% stddev median)], - event_headers => [qw(pct total min max avg 95% stddev median)], hidden_attrib => { # Don't sort/print these attribs in the reports. arg => 1, # They're usually handled specially, or not fingerprint => 1, # printed at all. @@ -6387,18 +7120,7 @@ sub new { ts => 1, }, }; - return bless $self, $class; -} - -sub set_report_formatter { - my ( $self, %args ) = @_; - my @required_args = qw(report formatter); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless exists $args{$arg}; - } - my ($report, $formatter) = @args{@required_args}; - $self->{formatter_for}->{$report} = $formatter; - return; + return $self; } sub print_reports { @@ -6504,7 +7226,7 @@ sub header { shorten(scalar keys %{$results->{classes}}, d=>1_000), shorten($qps || 0, d=>1_000), shorten($conc || 0, d=>1_000)); - $line .= ('_' x (LINE_LENGTH - length($line) + $self->{label_width} - 12)); + $line .= ('_' x (LINE_LENGTH - length($line) + $self->label_width() - 12)); push @result, $line; if ( my $ts = $results->{globals}->{ts} ) { @@ -6565,8 +7287,8 @@ sub header { return join("\n", map { s/\s+$//; $_ } @result) . "\n"; } -sub query_report { - my ( $self, %args ) = @_; +sub query_report_values { + my ($self, %args) = @_; foreach my $arg ( qw(ea worst orderby groupby) ) { die "I need a $arg argument" unless defined $arg; } @@ -6574,11 +7296,63 @@ sub query_report { my $groupby = $args{groupby}; my $worst = $args{worst}; - my $o = $self->{OptionParser}; - my $q = $self->{Quoter}; + my $q = $self->Quoter; my $qv = $self->{QueryReview}; my $qr = $self->{QueryRewriter}; + my @values; + ITEM: + foreach my $top_event ( @$worst ) { + my $item = $top_event->[0]; + my $reason = $args{explain_why} ? $top_event->[1] : ''; + my $rank = $top_event->[2]; + my $stats = $ea->results->{classes}->{$item}; + my $sample = $ea->results->{samples}->{$item}; + my $samp_query = $sample->{arg} || ''; + + my %item_vals = ( + item => $item, + samp_query => $samp_query, + rank => ($rank || 0), + reason => $reason, + ); + + my $review_vals; + if ( $qv ) { + $review_vals = $qv->get_review_info($item); + next ITEM if $review_vals->{reviewed_by} && !$self->{options}->{report_all}; + for my $col ( $qv->review_cols() ) { + push @{$item_vals{review_vals}}, [$col, $review_vals->{$col}]; + } + } + + $item_vals{default_db} = $sample->{db} ? $sample->{db} + : $stats->{db}->{unq} ? keys %{$stats->{db}->{unq}} + : undef; + $item_vals{tables} = [$self->{QueryParser}->extract_tables( + query => $samp_query, + default_db => $item_vals{default_db}, + Quoter => $self->Quoter, + )]; + + if ( $samp_query && ($args{variations} && @{$args{variations}}) ) { + $item_vals{crc} = crc32($samp_query); + } + + push @values, \%item_vals; + } + return \@values; +} + +sub query_report { + my ( $self, %args ) = @_; + + my $ea = $args{ea}; + my $groupby = $args{groupby}; + my $report_values = $self->query_report_values(%args); + + my $qr = $self->{QueryRewriter}; + my $report = ''; if ( $args{print_header} ) { @@ -6593,55 +7367,31 @@ sub query_report { ); ITEM: - foreach my $top_event ( @$worst ) { - my $item = $top_event->[0]; - my $reason = $args{explain_why} ? $top_event->[1] : ''; - my $rank = $top_event->[2]; - my $stats = $ea->results->{classes}->{$item}; - my $sample = $ea->results->{samples}->{$item}; - my $samp_query = $sample->{arg} || ''; - - my $review_vals; - if ( $qv ) { - $review_vals = $qv->get_review_info($item); - next ITEM if $review_vals->{reviewed_by} && !$o->get('report-all'); - } - - my ($default_db) = $sample->{db} ? $sample->{db} - : $stats->{db}->{unq} ? keys %{$stats->{db}->{unq}} - : undef; - my @tables; - if ( $o->get('for-explain') ) { - @tables = $self->{QueryParser}->extract_tables( - query => $samp_query, - default_db => $default_db, - Quoter => $self->{Quoter}, - ); - } - - $report .= "\n" if $rank > 1; # space between each event report + foreach my $vals ( @$report_values ) { + my $item = $vals->{item}; + $report .= "\n" if $vals->{rank} > 1; # space between each event report $report .= $self->event_report( %args, item => $item, - sample => $sample, - rank => $rank, - reason => $reason, + sample => $ea->results->{samples}->{$item}, + rank => $vals->{rank}, + reason => $vals->{reason}, attribs => $attribs, - db => $default_db, + db => $vals->{default_db}, ); - if ( $o->get('report-histogram') ) { + if ( $self->{options}->{report_histogram} ) { $report .= $self->chart_distro( %args, - attrib => $o->get('report-histogram'), - item => $item, + attrib => $self->{options}->{report_histogram}, + item => $vals->{item}, ); } - if ( $qv && $review_vals ) { + if ( $vals->{review_vals} ) { $report .= "# Review information\n"; - foreach my $col ( $qv->review_cols() ) { - my $val = $review_vals->{$col}; + foreach my $elem ( @{$vals->{review_vals}} ) { + my ($col, $val) = @$elem; if ( !$val || $val ne '0000-00-00 00:00:00' ) { # issue 202 $report .= sprintf "# %13s: %-s\n", $col, ($val ? $val : ''); } @@ -6649,18 +7399,15 @@ sub query_report { } if ( $groupby eq 'fingerprint' ) { - $samp_query = $qr->shorten($samp_query, $o->get('shorten')) - if $o->get('shorten'); + my $samp_query = $qr->shorten($vals->{samp_query}, $self->{options}->{shorten}) + if $self->{options}->{shorten}; - $report .= "# Fingerprint\n# $item\n" - if $o->get('fingerprints'); + PTDEBUG && _d("Fingerprint\n# $vals->{item}\n"); - $report .= $self->tables_report(@tables) - if $o->get('for-explain'); + $report .= $self->tables_report(@{$vals->{tables}}); - if ( $samp_query && ($args{variations} && @{$args{variations}}) ) { - my $crc = crc32($samp_query); - $report.= "# CRC " . ($crc ? $crc % 1_000 : "") . "\n"; + if ( $vals->{crc} ) { + $report.= "# CRC " . ($vals->{crc} % 1_000) . "\n"; } my $log_type = $args{log_type} || ''; @@ -6674,14 +7421,13 @@ sub query_report { } else { $report .= "# EXPLAIN /*!50100 PARTITIONS*/\n$samp_query${mark}\n"; - $report .= $self->explain_report($samp_query, $default_db); + $report .= $self->explain_report($samp_query, $vals->{default_db}); } } else { $report .= "$samp_query${mark}\n"; my $converted = $qr->convert_to_select($samp_query); - if ( $o->get('for-explain') - && $converted + if ( $converted && $converted =~ m/^[\(\s]*select/i ) { $report .= "# Converted for EXPLAIN\n# EXPLAIN /*!50100 PARTITIONS*/\n$converted${mark}\n"; } @@ -6689,7 +7435,7 @@ sub query_report { } else { if ( $groupby eq 'tables' ) { - my ( $db, $tbl ) = $q->split_unquote($item); + my ( $db, $tbl ) = $self->Quoter->split_unquote($item); $report .= $self->tables_report([$db, $tbl]); } $report .= "$item\n"; @@ -6699,20 +7445,19 @@ sub query_report { return $report; } -sub event_report { - my ( $self, %args ) = @_; - foreach my $arg ( qw(ea item orderby) ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my $ea = $args{ea}; - my $item = $args{item}; +sub event_report_values { + my ($self, %args) = @_; + + my $ea = $args{ea}; + my $item = $args{item}; my $orderby = $args{orderby}; my $results = $ea->results(); - my $o = $self->{OptionParser}; - my @result; + + my %vals; my $store = $results->{classes}->{$item}; - return "# No such event $item\n" unless $store; + + return unless $store; my $global_cnt = $results->{globals}->{$orderby}->{cnt}; my $class_cnt = $store->{$orderby}->{cnt}; @@ -6731,68 +7476,26 @@ sub event_report { }; } - my $line = sprintf( - '# %s %d: %s QPS, %sx concurrency, ID 0x%s at byte %.f ', - ($ea->{groupby} eq 'fingerprint' ? 'Query' : 'Item'), - $args{rank} || 0, - shorten($qps || 0, d=>1_000), - shorten($conc || 0, d=>1_000), - make_checksum($item), - $results->{samples}->{$item}->{pos_in_log} || 0, - ); - $line .= ('_' x (LINE_LENGTH - length($line) + $self->{label_width} - 12)); - push @result, $line; - - if ( $args{reason} ) { - push @result, - "# This item is included in the report because it matches " - . ($args{reason} eq 'top' ? '--limit.' : '--outliers.'); - } - - { + $vals{groupby} = $ea->{groupby}; + $vals{qps} = $qps || 0; + $vals{concurrency} = $conc || 0; + $vals{checksum} = make_checksum($item); + $vals{pos_in_log} = $results->{samples}->{$item}->{pos_in_log} || 0; + $vals{reason} = $args{reason}; + $vals{variance_to_mean} = do { my $query_time = $ea->metrics(where => $item, attrib => 'Query_time'); - push @result, - sprintf("# Scores: Apdex = %s [%3.1f]%s, V/M = %.2f", - (defined $query_time->{apdex} ? "$query_time->{apdex}" : "NS"), - ($query_time->{apdex_t} || 0), - ($query_time->{cnt} < 100 ? "*" : ""), - ($query_time->{stddev}**2 / ($query_time->{avg} || 1)), - ); + $query_time->{stddev}**2 / ($query_time->{avg} || 1) + }; + + $vals{counts} = { + class_cnt => $class_cnt, + global_cnt => $global_cnt, + }; + + if ( my $ts = $store->{ts}) { + $vals{time_range} = $self->format_time_range($ts) || "unknown"; } - if ( $o->get('explain') && $results->{samples}->{$item}->{arg} ) { - eval { - my $sparkline = $self->explain_sparkline( - $results->{samples}->{$item}->{arg}, $args{db}); - push @result, "# EXPLAIN sparkline: $sparkline\n"; - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d("Failed to get EXPLAIN sparkline:", $EVAL_ERROR); - } - } - - if ( my $attrib = $o->get('report-histogram') ) { - my $sparkline = $self->distro_sparkline( - %args, - attrib => $attrib, - item => $item, - ); - if ( $sparkline ) { - push @result, "# $attrib sparkline: |$sparkline|"; - } - } - - if ( my $ts = $store->{ts} ) { - my $time_range = $self->format_time_range($ts) || "unknown"; - push @result, "# Time range: $time_range"; - } - - push @result, $self->make_event_header(); - - push @result, - sprintf $self->{num_format}, 'Count', - percentage_of($class_cnt, $global_cnt), $class_cnt, map { '' } (1..8); - my $attribs = $args{attribs}; if ( !$attribs ) { $attribs = $self->sort_attribs( @@ -6801,10 +7504,9 @@ sub event_report { ); } + $vals{attributes} = { map { $_ => [] } qw(num innodb bool string) }; + foreach my $type ( qw(num innodb) ) { - if ( $type eq 'innodb' && @{$attribs->{$type}} ) { - push @result, "# InnoDB:"; - }; NUM_ATTRIB: foreach my $attrib ( @{$attribs->{$type}} ) { @@ -6824,15 +7526,12 @@ sub event_report { $pct = percentage_of( $vals->{sum}, $results->{globals}->{$attrib}->{sum}); - push @result, - sprintf $self->{num_format}, - $self->make_label($attrib), $pct, @values; + push @{$vals{attributes}{$type}}, + [ $attrib, $pct, @values ]; } } if ( @{$attribs->{bool}} ) { - push @result, "# Boolean:"; - my $printed_bools = 0; BOOL_ATTRIB: foreach my $attrib ( @{$attribs->{bool}} ) { next BOOL_ATTRIB unless exists $store->{$attrib}; @@ -6840,33 +7539,115 @@ sub event_report { next unless scalar %$vals; if ( $vals->{sum} > 0 ) { - push @result, - sprintf $self->{bool_format}, - $self->make_label($attrib), $self->bool_percents($vals); - $printed_bools = 1; + push @{$vals{attributes}{bool}}, + [ $attrib, $self->bool_percents($vals) ]; } } - pop @result unless $printed_bools; } if ( @{$attribs->{string}} ) { - push @result, "# String:"; - my $printed_strings = 0; STRING_ATTRIB: foreach my $attrib ( @{$attribs->{string}} ) { next STRING_ATTRIB unless exists $store->{$attrib}; my $vals = $store->{$attrib}; next unless scalar %$vals; + push @{$vals{attributes}{string}}, + [ $attrib, $vals ]; + } + } + + + return \%vals; +} + + +sub event_report { + my ( $self, %args ) = @_; + foreach my $arg ( qw(ea item orderby) ) { + die "I need a $arg argument" unless defined $args{$arg}; + } + + my $item = $args{item}; + my $val = $self->event_report_values(%args); + my @result; + + return "# No such event $item\n" unless $val; + + my $line = sprintf( + '# %s %d: %s QPS, %sx concurrency, ID 0x%s at byte %.f ', + ($val->{groupby} eq 'fingerprint' ? 'Query' : 'Item'), + $args{rank} || 0, + shorten($val->{qps}, d=>1_000), + shorten($val->{concurrency}, d=>1_000), + $val->{checksum}, + $val->{pos_in_log}, + ); + $line .= ('_' x (LINE_LENGTH - length($line) + $self->label_width() - 12)); + push @result, $line; + + if ( $val->{reason} ) { + push @result, + "# This item is included in the report because it matches " + . ($val->{reason} eq 'top' ? '--limit.' : '--outliers.'); + } + + push @result, + sprintf("# Scores: V/M = %.2f", $val->{variance_to_mean} ); + + if ( $val->{time_range} ) { + push @result, "# Time range: $val->{time_range}"; + } + + push @result, $self->make_event_header(); + + push @result, + sprintf $self->{num_format}, 'Count', + percentage_of($val->{counts}{class_cnt}, $val->{counts}{global_cnt}), + $val->{counts}{class_cnt}, + map { '' } (1..8); + + + my $attribs = $val->{attributes}; + + foreach my $type ( qw(num innodb) ) { + if ( $type eq 'innodb' && @{$attribs->{$type}} ) { + push @result, "# InnoDB:"; + }; + + NUM_ATTRIB: + foreach my $attrib ( @{$attribs->{$type}} ) { + my ($attrib_name, @vals) = @$attrib; + push @result, + sprintf $self->{num_format}, + $self->make_label($attrib_name), @vals; + } + } + + if ( @{$attribs->{bool}} ) { + push @result, "# Boolean:"; + BOOL_ATTRIB: + foreach my $attrib ( @{$attribs->{bool}} ) { + my ($attrib_name, @vals) = @$attrib; + push @result, + sprintf $self->{bool_format}, + $self->make_label($attrib_name), @vals; + } + } + + if ( @{$attribs->{string}} ) { + push @result, "# String:"; + STRING_ATTRIB: + foreach my $attrib ( @{$attribs->{string}} ) { + my ($attrib_name, $vals) = @$attrib; push @result, sprintf $self->{string_format}, - $self->make_label($attrib), - $self->format_string_list($attrib, $vals, $class_cnt); - $printed_strings = 1; + $self->make_label($attrib_name), + $self->format_string_list($attrib_name, $vals, $val->{counts}{class_cnt}); } - pop @result unless $printed_strings; } + return join("\n", map { s/\s+$//; $_ } @result) . "\n"; } @@ -6918,73 +7699,6 @@ sub chart_distro { return join("\n", @results) . "\n"; } - -sub distro_sparkline { - my ( $self, %args ) = @_; - foreach my $arg ( qw(ea item attrib) ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my $ea = $args{ea}; - my $item = $args{item}; - my $attrib = $args{attrib}; - - my $results = $ea->results(); - my $store = $results->{classes}->{$item}->{$attrib}; - my $vals = $store->{all}; - - my $all_zeros_sparkline = " " x 8; - - return $all_zeros_sparkline unless defined $vals && scalar %$vals; - - my @buck_tens = $ea->buckets_of(10); - my @distro = map { 0 } (0 .. 7); - my @buckets = map { 0 } (0..999); - map { $buckets[$_] = $vals->{$_} } keys %$vals; - $vals = \@buckets; - map { $distro[$buck_tens[$_]] += $vals->[$_] } (1 .. @$vals - 1); - - my $vals_per_mark; - my $max_val = 0; - my $max_disp_width = 64; - foreach my $n_vals ( @distro ) { - $max_val = $n_vals if $n_vals > $max_val; - } - $vals_per_mark = $max_val / $max_disp_width; - - my ($min, $max); - foreach my $i ( 0 .. $#distro ) { - my $n_vals = $distro[$i]; - my $n_marks = $n_vals / ($vals_per_mark || 1); - $n_marks = 1 if $n_marks < 1 && $n_vals > 0; - - $min = $n_marks if $n_marks && (!$min || $n_marks < $min); - $max = $n_marks if !$max || $n_marks > $max; - } - return $all_zeros_sparkline unless $min && $max; - - - $min = 0 if $min == $max; - my @range_min; - my $d = floor((($max+0.00001)-$min) / 4); - for my $x ( 1..4 ) { - push @range_min, $min + ($d * $x); - } - - my $sparkline = ""; - foreach my $i ( 0 .. $#distro ) { - my $n_vals = $distro[$i]; - my $n_marks = $n_vals / ($vals_per_mark || 1); - $n_marks = 1 if $n_marks < 1 && $n_vals > 0; - $sparkline .= $n_marks <= 0 ? ' ' - : $n_marks <= $range_min[0] ? '_' - : $n_marks <= $range_min[1] ? '.' - : $n_marks <= $range_min[2] ? '-' - : '^'; - } - - return $sparkline; -} - sub profile { my ( $self, %args ) = @_; foreach my $arg ( qw(ea worst groupby) ) { @@ -6996,7 +7710,6 @@ sub profile { my $groupby = $args{groupby}; my $qr = $self->{QueryRewriter}; - my $o = $self->{OptionParser}; my $results = $ea->results(); my $total_r = $results->{globals}->{Query_time}->{sum} || 0; @@ -7018,40 +7731,20 @@ sub profile { $qr->distill($samp_query, %{$args{distill_args}}) : $item, id => $groupby eq 'fingerprint' ? make_checksum($item) : '', vmr => ($query_time->{stddev}**2) / ($query_time->{avg} || 1), - apdex => defined $query_time->{apdex} ? $query_time->{apdex} : "NS", ); - if ( $o->get('explain') && $samp_query ) { - my ($default_db) = $sample->{db} ? $sample->{db} - : $stats->{db}->{unq} ? keys %{$stats->{db}->{unq}} - : undef; - eval { - $profile{explain_sparkline} = $self->explain_sparkline( - $samp_query, $default_db); - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d("Failed to get EXPLAIN sparkline:", $EVAL_ERROR); - } - } - push @profiles, \%profile; } - my $report = $self->{formatter_for}->{profile} || new ReportFormatter( - line_width => LINE_LENGTH, - long_last_column => 1, - extend_right => 1, - ); - $report->set_title('Profile'); + my $report = $self->ReportFormatter(); + $report->title('Profile'); my @cols = ( { name => 'Rank', right_justify => 1, }, { name => 'Query ID', }, { name => 'Response time', right_justify => 1, }, { name => 'Calls', right_justify => 1, }, { name => 'R/Call', right_justify => 1, }, - { name => 'Apdx', right_justify => 1, width => 4, }, { name => 'V/M', right_justify => 1, width => 5, }, - ( $o->get('explain') ? { name => 'EXPLAIN' } : () ), { name => 'Item', }, ); $report->set_columns(@cols); @@ -7067,9 +7760,7 @@ sub profile { "$rt $rtp", $item->{cnt}, $rc, - $item->{apdex}, $vmr, - ( $o->get('explain') ? $item->{explain_sparkline} || "" : () ), $item->{sample}, ); $report->add_line(@vals); @@ -7095,9 +7786,7 @@ sub profile { "$rt $rtp", $misc->{cnt}, $rc, - 'NS', # Apdex is not meaningful here '0.0', # variance-to-mean ratio is not meaningful here - ( $o->get('explain') ? "MISC" : () ), "<".scalar @$other." ITEMS>", ); } @@ -7182,12 +7871,8 @@ sub prepared { return unless scalar @prepared; - my $report = $self->{formatter_for}->{prepared} || new ReportFormatter( - line_width => LINE_LENGTH, - long_last_column => 1, - extend_right => 1, - ); - $report->set_title('Prepared statements'); + my $report = $self->ReportFormatter(); + $report->title('Prepared statements'); $report->set_columns( { name => 'Rank', right_justify => 1, }, { name => 'Query ID', }, @@ -7221,11 +7906,11 @@ sub make_global_header { my @lines; push @lines, - sprintf $self->{num_format}, "Attribute", '', @{$self->{global_headers}}; + sprintf $self->{num_format}, "Attribute", '', @{$self->global_headers()}; push @lines, sprintf $self->{num_format}, - (map { "=" x $_ } $self->{label_width}), + (map { "=" x $_ } $self->label_width()), (map { " " x $_ } qw(3)), # no pct column in global header (map { "=" x $_ } qw(7 7 7 7 7 7 7)); @@ -7239,11 +7924,11 @@ sub make_event_header { my @lines; push @lines, - sprintf $self->{num_format}, "Attribute", @{$self->{event_headers}}; + sprintf $self->{num_format}, "Attribute", @{$self->event_headers()}; push @lines, sprintf $self->{num_format}, - map { "=" x $_ } ($self->{label_width}, qw(3 7 7 7 7 7 7 7)); + map { "=" x $_ } ($self->label_width(), qw(3 7 7 7 7 7 7 7)); $self->{event_header_lines} = \@lines; return @lines; @@ -7258,7 +7943,7 @@ sub make_label { if ( $val =~ m/^InnoDB/ ) { $val =~ s/^InnoDB //; $val = $val eq 'trx id' ? "InnoDB trxID" - : substr($val, 0, $self->{label_width}); + : substr($val, 0, $self->label_width()); } $val = $val eq 'user' ? 'Users' @@ -7269,7 +7954,7 @@ sub make_label { : $val eq 'bytes' ? 'Query size' : $val eq 'Tmp disk tables' ? 'Tmp disk tbl' : $val eq 'Tmp table sizes' ? 'Tmp tbl size' - : substr($val, 0, $self->{label_width}); + : substr($val, 0, $self->label_width); return $val; } @@ -7283,8 +7968,7 @@ sub bool_percents { sub format_string_list { my ( $self, $attrib, $vals, $class_cnt ) = @_; - my $o = $self->{OptionParser}; - my $show_all = $o->get('show-all'); + my $show_all = $self->{options}->{show_all}; if ( !exists $vals->{unq} ) { return ($vals->{cnt}); @@ -7414,7 +8098,7 @@ sub pref_sort { sub tables_report { my ( $self, @tables ) = @_; return '' unless @tables; - my $q = $self->{Quoter}; + my $q = $self->Quoter(); my $tables = ""; foreach my $db_tbl ( @tables ) { my ( $db, $tbl ) = @$db_tbl; @@ -7433,7 +8117,7 @@ sub explain_report { return '' unless $query; my $dbh = $self->{dbh}; - my $q = $self->{Quoter}; + my $q = $self->Quoter(); my $qp = $self->{QueryParser}; return '' unless $dbh && $q && $qp; @@ -7482,34 +8166,6 @@ sub format_time_range { return $min && $max ? "$min to $max" : ''; } -sub explain_sparkline { - my ( $self, $query, $db ) = @_; - return unless $query; - - my $q = $self->{Quoter}; - my $dbh = $self->{dbh}; - my $ex = $self->{ExplainAnalyzer}; - return unless $dbh && $ex; - - if ( $db ) { - PTDEBUG && _d($dbh, "USE", $db); - $dbh->do("USE " . $q->quote($db)); - } - my $res = $ex->normalize( - $ex->explain_query( - dbh => $dbh, - query => $query, - ) - ); - - my $sparkline; - if ( $res ) { - $sparkline = $ex->sparkline(explain => $res); - } - - return $sparkline; -} - sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -7518,12 +8174,147 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } +no Lmo; 1; } # ########################################################################### # End QueryReportFormatter package # ########################################################################### +# ########################################################################### +# JSONReportFormatter package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/JSONReportFormatter.pm +# t/lib/JSONReportFormatter.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package JSONReportFormatter; +use Lmo; + +use List::Util qw(sum); +use Transformers qw(make_checksum parse_timestamp); + +use constant PTDEBUG => $ENV{PTDEBUG} || 0; + +my $have_json = eval { require JSON }; + +our $pretty_json = undef; +our $sorted_json = undef; + +extends qw(QueryReportFormatter); + +has _json => ( + is => 'ro', + init_arg => undef, + builder => '_build_json', +); + +sub _build_json { + return unless $have_json; + return JSON->new->utf8 + ->pretty($pretty_json) + ->canonical($sorted_json); +} + +sub encode_json { + my ($self, $encode) = @_; + if ( my $json = $self->_json ) { + return $json->encode($encode); + } + else { + return Transformers::encode_json($encode); + } +} + +override [qw(rusage date hostname files header profile prepared)] => sub { + return; +}; + +override event_report => sub { + my ($self, %args) = @_; + return $self->event_report_values(%args); +}; + +override query_report => sub { + my ($self, %args) = @_; + foreach my $arg ( qw(ea worst orderby groupby) ) { + die "I need a $arg argument" unless defined $arg; + } + + my $ea = $args{ea}; + my $worst = $args{worst}; + + my @attribs = @{$ea->get_attributes()}; + + my @queries; + foreach my $worst_info ( @$worst ) { + my $item = $worst_info->[0]; + my $stats = $ea->results->{classes}->{$item}; + my $sample = $ea->results->{samples}->{$item}; + + my $all_log_pos = $ea->{result_classes}->{$item}->{pos_in_log}->{all}; + my $times_seen = sum values %$all_log_pos; + + my %class = ( + sample => $sample->{arg}, + fingerprint => $item, + checksum => make_checksum($item), + cnt => $times_seen, + ); + + my %metrics; + foreach my $attrib ( @attribs ) { + $metrics{$attrib} = $ea->metrics( + attrib => $attrib, + where => $item, + ); + } + + foreach my $attrib ( keys %metrics ) { + if ( ! grep { $_ } values %{$metrics{$attrib}} ) { + delete $metrics{$attrib}; + next; + } + + if ($attrib eq 'ts') { + my $ts = delete $metrics{ts}; + foreach my $thing ( qw(min max) ) { + next unless defined $ts && defined $ts->{$thing}; + $ts->{$thing} = parse_timestamp($ts->{$thing}); + } + $class{ts_min} = $ts->{min}; + $class{ts_max} = $ts->{max}; + } + elsif ( ($ea->{type_for}->{$attrib} || '') eq 'num' ) { + for my $value ( values %{$metrics{$attrib}} ) { + next unless $value; + $value = sprintf '%.6f', $value; + } + if ( my $pct = $metrics{$attrib}->{pct} ) { + $metrics{$attrib}->{pct} = sprintf('%.2f', $pct); + } + } + } + push @queries, { + class => \%class, + attributes => \%metrics, + }; + } + + my $json = $self->encode_json(\@queries); + $json .= "\n" if $json !~ /\n\Z/; + return $json . "\n"; +}; + +no Lmo; +1; +} +# ########################################################################### +# End JSONReportFormatter package +# ########################################################################### + # ########################################################################### # EventTimeline package # This package is a copy without comments from the original. The original @@ -8320,7 +9111,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); @@ -8585,7 +9376,7 @@ sub new { sub set_history_options { my ( $self, %args ) = @_; - foreach my $arg ( qw(table dbh tbl_struct col_pat) ) { + foreach my $arg ( qw(table tbl_struct col_pat) ) { die "I need a $arg argument" unless $args{$arg}; } @@ -8619,7 +9410,7 @@ sub set_history_options { } @cols) . ')'; PTDEBUG && _d($sql); - $self->{history_sth} = $args{dbh}->prepare($sql); + $self->{history_sth} = $self->{dbh}->prepare($sql); $self->{history_metrics} = \@metrics; return; @@ -10346,143 +11137,6 @@ sub _d { # End HTTPProtocolParser package # ########################################################################### -# ########################################################################### -# ExecutionThrottler package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/ExecutionThrottler.pm -# t/lib/ExecutionThrottler.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package ExecutionThrottler; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use List::Util qw(sum min max); -use Time::HiRes qw(time); -use Data::Dumper; -$Data::Dumper::Indent = 1; -$Data::Dumper::Sortkeys = 1; -$Data::Dumper::Quotekeys = 0; - -sub new { - my ( $class, %args ) = @_; - my @required_args = qw(rate_max get_rate check_int step); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my $self = { - step => 0.05, # default - %args, - rate_ok => undef, - last_check => undef, - stats => { - rate_avg => 0, - rate_samples => [], - }, - int_rates => [], - skip_prob => 0.0, - }; - - return bless $self, $class; -} - -sub throttle { - my ( $self, %args ) = @_; - my $time = $args{misc}->{time} || time; - if ( $self->_time_to_check($time) ) { - my $rate_avg = (sum(@{$self->{int_rates}}) || 0) - / (scalar @{$self->{int_rates}} || 1); - my $running_avg = $self->_save_rate_avg($rate_avg); - PTDEBUG && _d('Average rate for last interval:', $rate_avg); - - if ( $args{stats} ) { - $args{stats}->{throttle_checked_rate}++; - $args{stats}->{throttle_rate_avg} = sprintf '%.2f', $running_avg; - } - - @{$self->{int_rates}} = (); - - if ( $rate_avg > $self->{rate_max} ) { - $self->{skip_prob} += $self->{step}; - $self->{skip_prob} = 1.0 if $self->{skip_prob} > 1.0; - PTDEBUG && _d('Rate max exceeded'); - $args{stats}->{throttle_rate_max_exceeded}++ if $args{stats}; - } - else { - $self->{skip_prob} -= $self->{step}; - $self->{skip_prob} = 0.0 if $self->{skip_prob} < 0.0; - $args{stats}->{throttle_rate_ok}++ if $args{stats}; - } - - PTDEBUG && _d('Skip probability:', $self->{skip_prob}); - $self->{last_check} = $time; - } - else { - my $current_rate = $self->{get_rate}->(); - push @{$self->{int_rates}}, $current_rate; - if ( $args{stats} ) { - $args{stats}->{throttle_rate_min} = min( - ($args{stats}->{throttle_rate_min} || ()), $current_rate); - $args{stats}->{throttle_rate_max} = max( - ($args{stats}->{throttle_rate_max} || ()), $current_rate); - } - PTDEBUG && _d('Current rate:', $current_rate); - } - - if ( $args{event} ) { - $args{event}->{Skip_exec} = $self->{skip_prob} <= rand() ? 'No' : 'Yes'; - } - - return $args{event}; -} - -sub _time_to_check { - my ( $self, $time ) = @_; - if ( !$self->{last_check} ) { - $self->{last_check} = $time; - return 0; - } - return $time - $self->{last_check} >= $self->{check_int} ? 1 : 0; -} - -sub rate_avg { - my ( $self ) = @_; - return $self->{stats}->{rate_avg} || 0; -} - -sub skip_probability { - my ( $self ) = @_; - return $self->{skip_prob}; -} - -sub _save_rate_avg { - my ( $self, $rate ) = @_; - my $samples = $self->{stats}->{rate_samples}; - push @$samples, $rate; - shift @$samples if @$samples > 1_000; - $self->{stats}->{rate_avg} = sum(@$samples) / (scalar @$samples); - return $self->{stats}->{rate_avg} || 0; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End ExecutionThrottler package -# ########################################################################### - # ########################################################################### # MasterSlave package # This package is a copy without comments from the original. The original @@ -11444,226 +12098,6 @@ sub _d { # End FileIterator package # ########################################################################### -# ########################################################################### -# ExplainAnalyzer package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/ExplainAnalyzer.pm -# t/lib/ExplainAnalyzer.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package ExplainAnalyzer; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use Data::Dumper; -$Data::Dumper::Indent = 1; -$Data::Dumper::Sortkeys = 1; -$Data::Dumper::Quotekeys = 0; - -sub new { - my ( $class, %args ) = @_; - foreach my $arg ( qw(QueryRewriter QueryParser) ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my $self = { - %args, - }; - return bless $self, $class; -} - -sub explain_query { - my ( $self, %args ) = @_; - foreach my $arg ( qw(dbh query) ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my ($query, $dbh) = @args{qw(query dbh)}; - $query = $self->{QueryRewriter}->convert_to_select($query); - if ( $query !~ m/^\s*select/i ) { - PTDEBUG && _d("Cannot EXPLAIN non-SELECT query:", - (length $query <= 100 ? $query : substr($query, 0, 100) . "...")); - return; - } - my $sql = "EXPLAIN $query"; - PTDEBUG && _d($dbh, $sql); - my $explain = $dbh->selectall_arrayref($sql, { Slice => {} }); - PTDEBUG && _d("Result of EXPLAIN:", Dumper($explain)); - return $explain; -} - -sub normalize { - my ( $self, $explain ) = @_; - my @result; # Don't modify the input. - - foreach my $row ( @$explain ) { - $row = { %$row }; # Make a copy -- don't modify the input. - - foreach my $col ( qw(key possible_keys key_len ref) ) { - $row->{$col} = [ split(/,/, $row->{$col} || '') ]; - } - - $row->{Extra} = { - map { - my $var = $_; - - if ( my ($key, $vals) = $var =~ m/(Using union)\(([^)]+)\)/ ) { - $key => [ split(/,/, $vals) ]; - } - - else { - $var => 1; - } - } - split(/; /, $row->{Extra} || '') # Split on semicolons. - }; - - push @result, $row; - } - - return \@result; -} - -sub get_alternate_indexes { - my ( $self, $keys, $possible_keys ) = @_; - my %used = map { $_ => 1 } @$keys; - return [ grep { !$used{$_} } @$possible_keys ]; -} - -sub get_index_usage { - my ( $self, %args ) = @_; - foreach my $arg ( qw(query explain) ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my ($query, $explain) = @args{qw(query explain)}; - my @result; - - my $lookup = $self->{QueryParser}->get_aliases($query); - - foreach my $row ( @$explain ) { - - next if !defined $row->{table} - || $row->{table} =~ m/^<(derived|union)\d/; - - my $table = $lookup->{TABLE}->{$row->{table}} || $row->{table}; - my $db = $lookup->{DATABASE}->{$table} || $args{db}; - push @result, { - db => $db, - tbl => $table, - idx => $row->{key}, - alt => $self->get_alternate_indexes( - $row->{key}, $row->{possible_keys}), - }; - } - - PTDEBUG && _d("Index usage for", - (length $query <= 100 ? $query : substr($query, 0, 100) . "..."), - ":", Dumper(\@result)); - return \@result; -} - -sub get_usage_for { - my ( $self, $checksum, $db ) = @_; - die "I need a checksum and db" unless defined $checksum && defined $db; - my $usage; - if ( exists $self->{usage}->{$db} # Don't auto-vivify - && exists $self->{usage}->{$db}->{$checksum} ) - { - $usage = $self->{usage}->{$db}->{$checksum}; - } - PTDEBUG && _d("Usage for", - (length $checksum <= 100 ? $checksum : substr($checksum, 0, 100) . "..."), - "on", $db, ":", Dumper($usage)); - return $usage; -} - -sub save_usage_for { - my ( $self, $checksum, $db, $usage ) = @_; - die "I need a checksum and db" unless defined $checksum && defined $db; - $self->{usage}->{$db}->{$checksum} = $usage; -} - -sub fingerprint { - my ( $self, %args ) = @_; - my @required_args = qw(explain); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my ($explain) = @args{@required_args}; -} - -sub sparkline { - my ( $self, %args ) = @_; - my @required_args = qw(explain); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my ($explain) = @args{@required_args}; - PTDEBUG && _d("Making sparkline for", Dumper($explain)); - - my $access_code = { - 'ALL' => 'a', - 'const' => 'c', - 'eq_ref' => 'e', - 'fulltext' => 'f', - 'index' => 'i', - 'index_merge' => 'm', - 'range' => 'n', - 'ref_or_null' => 'o', - 'ref' => 'r', - 'system' => 's', - 'unique_subquery' => 'u', - }; - - my $sparkline = ''; - my ($T, $F); # Using temporary, Using filesort - - foreach my $tbl ( @$explain ) { - my $code; - if ( defined $tbl->{type} ) { - $code = $access_code->{$tbl->{type}} || "?"; - $code = uc $code if $tbl->{Extra}->{'Using index'}; - } - else { - $code = '-' - }; - $sparkline .= $code; - - $T = 1 if $tbl->{Extra}->{'Using temporary'}; - $F = 1 if $tbl->{Extra}->{'Using filesort'}; - } - - if ( $T || $F ) { - if ( $explain->[-1]->{Extra}->{'Using temporary'} - || $explain->[-1]->{Extra}->{'Using filesort'} ) { - $sparkline .= ">" . ($T ? "T" : "") . ($F ? "F" : ""); - } - else { - $sparkline = ($T ? "T" : "") . ($F ? "F" : "") . ">$sparkline"; - } - } - - PTDEBUG && _d("sparkline:", $sparkline); - return $sparkline; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End ExplainAnalyzer package -# ########################################################################### - # ########################################################################### # Runtime package # This package is a copy without comments from the original. The original @@ -11822,7 +12256,7 @@ sub new { } my $self = { - instrument => 0, + instrument => PTDEBUG, continue_on_error => 0, %args, @@ -11849,9 +12283,7 @@ sub add { push @{$self->{procs}}, $process; push @{$self->{names}}, $name; - if ( my $n = $args{retry_on_error} ) { - $self->{retries}->{$name} = $n; - } + $self->{retries}->{$name} = $args{retry_on_error} || 100; if ( $self->{instrument} ) { $self->{instrumentation}->{$name} = { time => 0, calls => 0 }; } @@ -11920,7 +12352,11 @@ sub execute { my $msg = "Pipeline process " . ($procno + 1) . " ($name) caused an error: " . $EVAL_ERROR; - if ( defined $self->{retries}->{$name} ) { + if ( !$self->{continue_on_error} ) { + die $msg . "Terminating pipeline because --continue-on-error " + . "is false.\n"; + } + elsif ( defined $self->{retries}->{$name} ) { my $n = $self->{retries}->{$name}; if ( $n ) { warn $msg . "Will retry pipeline process $procno ($name) " @@ -11932,9 +12368,6 @@ sub execute { . "($name) caused too many errors.\n"; } } - elsif ( !$self->{continue_on_error} ) { - die $msg; - } else { warn $msg; } @@ -11977,300 +12410,6 @@ sub _d { # End Pipeline package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -12960,7 +13099,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -13036,10 +13174,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -13050,13 +13187,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -13086,7 +13223,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -13269,6 +13406,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -13293,33 +13674,57 @@ sub _d { # ########################################################################### package pt_query_digest; +use strict; +use warnings FATAL => 'all'; use English qw(-no_match_vars); -use Time::Local qw(timelocal); -use Time::HiRes qw(time usleep); -use List::Util qw(max); -use POSIX qw(signal_h); -use Data::Dumper; -$Data::Dumper::Indent = 1; -$OUTPUT_AUTOFLUSH = 1; +use constant PTDEBUG => $ENV{PTDEBUG} || 0; -Transformers->import(qw(shorten micro_t percentage_of ts make_checksum - any_unix_timestamp parse_timestamp unix_timestamp crc32)); +use Time::Local qw(timelocal); +use Time::HiRes qw(time usleep); +use List::Util qw(max); +use Scalar::Util qw(looks_like_number); +use POSIX qw(signal_h); +use Data::Dumper; use Percona::Toolkit; -use constant PTDEBUG => $ENV{PTDEBUG} || 0; + +$Data::Dumper::Indent = 1; +$Data::Dumper::Sortkeys = 1; +$Data::Dumper::Quotekeys = 0; + +$OUTPUT_AUTOFLUSH = 1; + +Transformers->import(qw( + shorten + micro_t + percentage_of + ts + make_checksum + any_unix_timestamp + parse_timestamp + unix_timestamp + crc32 +)); use sigtrap 'handler', \&sig_int, 'normal-signals'; # Global variables. Only really essential variables should be here. my $oktorun = 1; -my $ex_dbh; # For --execute my $ep_dbh; # For --explain my $ps_dbh; # For Processlist my $aux_dbh; # For --aux-dsn (--since/--until "MySQL expression") +my $resume_file; +my $offset; + +(my $tool = __PACKAGE__) =~ tr/_/-/; + sub main { - local @ARGV = @_; # set global ARGV for this package - $oktorun = 1; # reset between tests else pipeline won't run + # Reset global vars, else tests will fail. + local @ARGV = @_; + $oktorun = 1; + $resume_file = undef; + $offset = undef; # ########################################################################## # Get configuration information. @@ -13344,31 +13749,11 @@ sub main { } if ( !$o->get('help') ) { - if ( $review_dsn - && (!defined $review_dsn->{D} || !defined $review_dsn->{t}) ) { - $o->save_error('The --review DSN requires a D (database) and t' - . ' (table) part specifying the query review table'); - } - if ( $o->get('mirror') - && (!$o->get('execute') || !$o->get('processlist')) ) { - $o->save_error('--mirror requires --execute and --processlist'); - } if ( $o->get('outliers') && grep { $_ !~ m/^\w+:[0-9.]+(?::[0-9.]+)?$/ } @{$o->get('outliers')} ) { $o->save_error('--outliers requires two or three colon-separated fields'); } - if ( $o->get('execute-throttle') ) { - my ($rate_max, $int, $step) = @{$o->get('execute-throttle')}; - $o->save_error("--execute-throttle max time must be between 1 and 100") - unless $rate_max && $rate_max > 0 && $rate_max <= 100; - $o->save_error("No check interval value for --execute-throttle") - unless $int; - $o->save_error("--execute-throttle check interval must be an integer") - if $int =~ m/[^\d]/; - $o->save_error("--execute-throttle step must be between 1 and 100") - if $step && ($step < 1 || $step > 100); - } if ( $o->get('progress') ) { eval { Progress->validate_spec($o->get('progress')) }; if ( $EVAL_ERROR ) { @@ -13377,9 +13762,20 @@ sub main { } } - if ( $o->get('apdex-threshold') <= 0 ) { - $o->save_error("Apdex threshold must be a positive decimal value"); + if ( my $review_dsn = $o->get('review') ) { + $o->save_error('--review does not accept a t option. Perhaps you meant ' + . 'to use --review-table or --history-table?') + if defined $review_dsn->{t}; } + + for my $tables ('review-table', 'history-table') { + my $got = $o->get($tables); + if ( grep !defined, Quoter->split_unquote($got) ) { + $o->save_error("--$tables should be passed a " + . "fully-qualified table name, got $got"); + } + } + if ( my $patterns = $o->get('embedded-attributes') ) { $o->save_error("--embedded-attributes should be passed two " . "comma-separated patterns, got " . scalar(@$patterns) ) @@ -13437,7 +13833,6 @@ sub main { # ######################################################################## # Set up for --explain # ######################################################################## - my $exa; if ( my $ep_dsn = $o->get('explain') ) { $ep_dbh = get_cxn( for => '--explain', @@ -13447,19 +13842,13 @@ sub main { opts => { AutoCommit => 1 }, ); $ep_dbh->{InactiveDestroy} = 1; # Don't die on fork(). - - $exa = new ExplainAnalyzer( - QueryRewriter => $qr, - QueryParser => $qp, - ); } # ######################################################################## - # Set up for --review and --review-history. + # Set up for --review. # ######################################################################## my $qv; # QueryReview my $qv_dbh; # For QueryReview - my $qv_dbh2; # For QueryReview and --review-history if ( $review_dsn ) { my $tp = new TableParser(Quoter => $q); $qv_dbh = get_cxn( @@ -13470,28 +13859,33 @@ sub main { opts => { AutoCommit => 1 }, ); $qv_dbh->{InactiveDestroy} = 1; # Don't die on fork(). - my @db_tbl = @{$review_dsn}{qw(D t)}; - my $db_tbl = $q->quote(@db_tbl); - # Create the review table if desired - if ( $o->get('create-review-table') ) { - my $sql = $o->read_para_after( - __FILE__, qr/MAGIC_create_review/); - $sql =~ s/query_review/IF NOT EXISTS $db_tbl/; - PTDEBUG && _d($sql); - $qv_dbh->do($sql); - } + my @db_tbl = Quoter->split_unquote($o->get('review-table')); + my @hdb_tbl = Quoter->split_unquote($o->get('history-table')); - # Check for the existence of the table. - if ( !$tp->check_table( - dbh => $qv_dbh, - db => $db_tbl[0], - tbl => $db_tbl[1]) ) - { - die "The query review table $db_tbl does not exist. " - . "Specify --create-review-table to create it, " - . "and ensure that the MySQL user has privileges to create " - . "and update the table.\n"; + my $db_tbl = $q->quote(@db_tbl); + my $hdb_tbl = $q->quote(@hdb_tbl); + + my $create_review_sql = $o->read_para_after( + __FILE__, qr/MAGIC_create_review/); + $create_review_sql =~ s/query_review/IF NOT EXISTS $db_tbl/; + + my $create_history_sql = $o->read_para_after( + __FILE__, qr/MAGIC_create_review_history/); + $create_history_sql =~ s/query_review_history/IF NOT EXISTS $hdb_tbl/; + + for my $create ( + [ $db_tbl, $create_review_sql ], + [ $hdb_tbl, $create_history_sql ], + ) { + my ($tbl_name, $sql) = @$create; + create_review_tables( + dbh => $qv_dbh, + full_table => $tbl_name, + create_table_sql => $sql, + create_table => $o->get('create-review-tables'), + TableParser => $tp, + ); } # Set up the new QueryReview object. @@ -13503,79 +13897,43 @@ sub main { quoter => $q, ); - # Set up the review-history table - if ( my $review_history_dsn = $o->get('review-history') ) { - $qv_dbh2 = get_cxn( - for => '--review-history', - dsn => $review_history_dsn, - OptionParser => $o, - DSNParser => $dp, - opts => { AutoCommit => 1 }, - ); - $qv_dbh2->{InactiveDestroy} = 1; # Don't die on fork(). - my @hdb_tbl = @{$o->get('review-history')}{qw(D t)}; - my $hdb_tbl = $q->quote(@hdb_tbl); - - # Create the review-history table if desired - if ( $o->get('create-review-history-table') ) { - my $sql = $o->read_para_after( - __FILE__, qr/MAGIC_create_review_history/); - $sql =~ s/query_review_history/IF NOT EXISTS $hdb_tbl/; - PTDEBUG && _d($sql); - $qv_dbh2->do($sql); - } - - # Check for the existence of the table. - if ( !$tp->check_table( - dbh => $qv_dbh2, - db => $hdb_tbl[0], - tbl => $hdb_tbl[1]) ) - { - die "The query review history table $hdb_tbl does not exist. " - . "Specify --create-review-history-table to create it, " - . "and ensure that the MySQL user has privileges to create " - . "and update the table.\n"; - } - - # Inspect for MAGIC_history_cols. Add them to the --select list - # only if an explicit --select list was given. Otherwise, leave - # --select undef which will cause EventAggregator to aggregate every - # attribute available which will include the history columns. - # If no --select list was given and we make one by adding the history - # columsn to it, then EventAggregator will only aggregate the - # history columns and nothing else--we don't want this. - my $tbl = $tp->parse($tp->get_create_table($qv_dbh2, @hdb_tbl)); - my $pat = $o->read_para_after(__FILE__, qr/MAGIC_history_cols/); - $pat =~ s/\s+//g; - $pat = qr/^(.*?)_($pat)$/; - # Get original --select values. - my %select = map { $_ => 1 } @{$o->get('select')}; - foreach my $col ( @{$tbl->{cols}} ) { - my ( $attr, $metric ) = $col =~ m/$pat/; - next unless $attr && $metric; - $attr = ucfirst $attr if $attr =~ m/_/; # TableParser lowercases - # Add history table values to original select values. - $select{$attr}++; - } - - if ( $o->got('select') ) { - # Re-set --select with its original values plus the history - # table values. - $o->set('select', [keys %select]); - PTDEBUG && _d("--select after parsing --review-history table:", - @{$o->get('select')}); - } - - # And tell the QueryReview that it has more work to do. - $qv->set_history_options( - table => $hdb_tbl, - dbh => $qv_dbh2, - tbl_struct => $tbl, - col_pat => $pat, - ); + # Inspect for MAGIC_history_cols. Add them to the --select list + # only if an explicit --select list was given. Otherwise, leave + # --select undef which will cause EventAggregator to aggregate every + # attribute available which will include the history columns. + # If no --select list was given and we make one by adding the history + # columsn to it, then EventAggregator will only aggregate the + # history columns and nothing else--we don't want this. + my $tbl = $tp->parse($tp->get_create_table($qv_dbh, @hdb_tbl)); + my $pat = $o->read_para_after(__FILE__, qr/MAGIC_history_cols/); + $pat =~ s/\s+//g; + $pat = qr/^(.*?)_($pat)$/; + # Get original --select values. + my %select = map { $_ => 1 } @{$o->get('select')}; + foreach my $col ( @{$tbl->{cols}} ) { + my ( $attr, $metric ) = $col =~ $pat; + next unless $attr && $metric; + $attr = ucfirst $attr if $attr =~ m/_/; # TableParser lowercases + # Add history table values to original select values. + $select{$attr}++; } + + if ( $o->got('select') ) { + # Re-set --select with its original values plus the history + # table values. + $o->set('select', [sort keys %select]); + PTDEBUG && _d("--select after parsing the history table:", + @{$o->get('select')}); + } + + # And tell the QueryReview that it has more work to do. + $qv->set_history_options( + table => $hdb_tbl, + tbl_struct => $tbl, + col_pat => $pat, + ); } - + # ######################################################################## # Create all the pipeline processes that do all the work: get input, # parse events, manage runtime, switch iterations, aggregate, etc. @@ -13596,13 +13954,7 @@ sub main { stats => \%stats, }; - # Enable timings to instrument code for either of these two opts. - # Else, don't instrument to avoid cost of measurement. - my $instrument = $o->get('pipeline-profile') || $o->get('execute-throttle'); - PTDEBUG && _d('Instrument:', $instrument); - my $pipeline = new Pipeline( - instrument => $instrument, continue_on_error => $o->get('continue-on-error'), ); @@ -13630,7 +13982,7 @@ sub main { } # prep { # input - my $fi = new FileIterator(); + my $fi = FileIterator->new(); my $next_file = $fi->get_file_itr(@ARGV); my $input_fh; # the current input fh my $pr; # Progress obj for ^ @@ -13639,20 +13991,51 @@ sub main { name => 'input', process => sub { my ( $args ) = @_; + # Only get the next file when there's no fh or no more events in # the current fh. This allows us to do collect-and-report cycles # (i.e. iterations) on huge files. This doesn't apply to infinite # inputs because they don't set more_events false. if ( !$args->{input_fh} || !$args->{more_events} ) { + + # Close the current file. if ( $args->{input_fh} ) { close $args->{input_fh} or die "Cannot close input fh: $OS_ERROR"; } + + # Open the next file. my ($fh, $filename, $filesize) = $next_file->(); if ( $fh ) { PTDEBUG && _d('Reading', $filename); + PTDEBUG && _d('File size:', $filesize); push @read_files, $filename || "STDIN"; + # Read the file offset for --resume. + if ( ($resume_file = $o->get('resume')) && $filename ) { + if ( -s $resume_file ) { + open my $resume_fh, '<', $resume_file + or die "Error opening $resume_file: $OS_ERROR"; + chomp(my $resume_offset = <$resume_fh>); + close $resume_fh + or die "Error close $resume_file: $OS_ERROR"; + if ( !looks_like_number($resume_offset) ) { + die "Offset $resume_offset in $resume_file " + . "does not look like a number.\n"; + } + PTDEBUG && _d('Resuming at offset', $resume_offset); + seek $fh, $resume_offset, 0 + or die "Error seeking to $resume_offset in " + . "$resume_file: $OS_ERROR"; + warn "Resuming $filename from offset $resume_offset " + . "(file size: $filesize)...\n"; + } + else { + PTDEBUG && _d('Not resuming', $filename, 'because', + $resume_file, 'does not exist'); + } + } + # Create callback to read next event. Some inputs, like # Processlist, may use something else but most next_event. if ( my $read_time = $o->get('read-timeout') ) { @@ -13662,8 +14045,15 @@ sub main { else { $args->{next_event} = sub { return <$fh>; }; } + $args->{filename} = $filename; $args->{input_fh} = $fh; - $args->{tell} = sub { return tell $fh; }; + $args->{tell} = sub { + $offset = tell $fh; # update global $offset + if ( $args->{filename} ) { + $args->{pos_for}->{$args->{filename}} = $offset; + } + return $offset; # legacy: return global $offset + }; $args->{more_events} = 1; # Reset in case we read two logs out of order by time. @@ -13722,14 +14112,12 @@ sub main { $err = $EVAL_ERROR; if ( $err ) { # Try to reconnect when there's an error. eval { - ($cur_server, $ps_dbh) = find_role( - OptionParser => $o, - DSNParser => $dp, - dbh => $ps_dbh, - current => $cur_server, - read_only => 0, - comment => 'for --processlist' - ); + if ( !$ps_dbh || !$ps_dbh->ping ) { + PTDEBUG && _d('Getting a dbh from', $cur_server); + $ps_dbh = $dp->get_dbh( + $dp->get_cxn_params($o->get($cur_server)), {AutoCommit => 1}); + $ps_dbh->{InactiveDestroy} = 1; # Don't die on fork(). + } $cur_time = time(); $sth = $ps_dbh->prepare('SHOW FULL PROCESSLIST'); $cxn = $ps_dbh->{mysql_thread_id}; @@ -13742,18 +14130,6 @@ sub main { } } } until ( $sth && !$err ); - if ( $o->get('mirror') - && time() - $cur_time > $o->get('mirror')) { - ($cur_server, $ps_dbh) = find_role( - OptionParser => $o, - DSNParser => $dp, - dbh => $ps_dbh, - current => $cur_server, - read_only => 0, - comment => 'for --processlist' - ); - $cur_time = time(); - } return [ grep { $_->[0] != $cxn } @{ $sth->fetchall_arrayref(); } ]; }; @@ -13946,7 +14322,7 @@ sub main { ); $aux_dbh->{InactiveDestroy} = 1; # Don't die on fork(). } - $aux_dbh ||= $qv_dbh || $qv_dbh2 || $ex_dbh || $ps_dbh || $ep_dbh; + $aux_dbh ||= $qv_dbh || $ps_dbh || $ep_dbh; PTDEBUG && _d('aux dbh:', $aux_dbh); my $time_callback = sub { @@ -14078,7 +14454,6 @@ sub main { files => \@read_files, Pipeline => $pipeline, QueryReview => $qv, - ExplainAnalyzer => $exa, %common_modules, ); } @@ -14086,7 +14461,38 @@ sub main { print "\n# No events processed.\n"; } - if ( $o->get('statistics') ) { + if ( PTDEBUG ) { + # Print statistics about internal counters. This option is mostly for + # development and debugging. The statistics report is printed for each + # iteration after all other reports, even if no events are processed or + # C<--no-report> is specified. The statistics report looks like: + + # No events processed. + + # Statistic Count %/Events + # ================================================ ====== ======== + # events_read 142030 100.00 + # events_parsed 50430 35.51 + # events_aggregated 0 0.00 + # ignored_midstream_server_response 18111 12.75 + # no_tcp_data 91600 64.49 + # pipeline_restarted_after_MemcachedProtocolParser 142030 100.00 + # pipeline_restarted_after_TcpdumpParser 1 0.00 + # unknown_client_command 1 0.00 + # unknown_client_data 32318 22.75 + + # The first column is the internal counter name; the second column is counter's + # count; and the third column is the count as a percentage of C. + + # In this case, it shows why no events were processed/aggregated: 100% of events + # were rejected by the C. Of those, 35.51% were data + # packets, but of these 12.75% of ignored mid-stream server response, one was + # an unknown client command, and 22.75% were unknown client data. The other + # 64.49% were TCP control packets (probably most ACKs). + + # Since pt-query-digest is complex, you will probably need someone familiar + # with its code to decipher the statistics report. + if ( keys %stats ) { my $report = new ReportFormatter( line_width => 74, @@ -14392,139 +14798,6 @@ sub main { } } # sample - my $ex_dsn; - { # execute throttle and execute - my $et; - if ( my $et_args = $o->get('execute-throttle') ) { - # These were check earlier; no need to check them again. - my ($rate_max, $int, $step) = @{$o->get('execute-throttle')}; - $step ||= 5; - $step /= 100; # step specified as percent but $et expect 0.1=10%, etc. - PTDEBUG && _d('Execute throttle:', $rate_max, $int, $step); - - my $get_rate = sub { - my $instrument = $pipeline->instrumentation; - return percentage_of( - $instrument->{execute}->{time} || 0, - $instrument->{Pipeline}->{time} || 0, - ); - }; - - $et = new ExecutionThrottler( - rate_max => $rate_max, - get_rate => $get_rate, - check_int => $int, - step => $step, - ); - - $pipeline->add( - name => 'execute throttle', - process => sub { - my ( $args ) = @_; - $args->{event} = $et->throttle( - event => $args->{event}, - stats => \%stats, - misc => $args->{misc}, - ); - return $args; - }, - ); - } # execute throttle - - if ( $ex_dsn = $o->get('execute') ) { - if ( $o->get('ask-pass') ) { - $ex_dsn->{p} = OptionParser::prompt_noecho("Enter password for " - . "--execute: "); - $o->set('execute', $ex_dsn); - } - - my $cur_server = 'execute'; - ($cur_server, $ex_dbh) = find_role( - OptionParser => $o, - DSNParser => $dp, - dbh => $ex_dbh, - current => $cur_server, - read_only => 1, - comment => 'for --execute' - ); - my $cur_time = time(); - my $curdb; - my $default_db = $o->get('execute')->{D}; - PTDEBUG && _d('Default db:', $default_db); - - $pipeline->add( - name => 'execute', - process => sub { - my ( $args ) = @_; - my $event = $args->{event}; - $event->{Exec_orig_time} = $event->{Query_time}; - if ( ($event->{Skip_exec} || '') eq 'Yes' ) { - PTDEBUG && _d('Not executing event because of ', - '--execute-throttle'); - # Zero Query_time to 'Exec time' will show the real time - # spent executing queries. - $event->{Query_time} = 0; - $stats{execute_skipped}++; - return $args; - } - $stats{execute_executed}++; - my $db = $event->{db} || $default_db; - eval { - if ( $db && (!$curdb || $db ne $curdb) ) { - $ex_dbh->do("USE $db"); - $curdb = $db; - } - my $start = time(); - $ex_dbh->do($event->{arg}); - my $end = time(); - $event->{Query_time} = $end - $start; - $event->{Exec_diff_time} - = $event->{Query_time} - $event->{Exec_orig_time}; - if ($o->get('mirror') && $end-$cur_time > $o->get('mirror')) { - ($cur_server, $ex_dbh) = find_role( - OptionParser => $o, - DSNParser => $dp, - dbh => $ex_dbh, - current => $cur_server, - read_only => 1, - comment => 'for --execute' - ); - $cur_time = $end; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d($EVAL_ERROR); - $stats{execute_error}++; - # Don't try to re-execute the statement. Just skip it. - if ( $EVAL_ERROR =~ m/server has gone away/ ) { - print STDERR $EVAL_ERROR; - eval { - ($cur_server, $ex_dbh) = find_role( - OptionParser => $o, - DSNParser => $dp, - dbh => $ex_dbh, - current => $cur_server, - read_only => 1, - comment => 'for --execute' - ); - $cur_time = time(); - }; - if ( $EVAL_ERROR ) { - print STDERR $EVAL_ERROR; - sleep 1; - } - return; - } - if ( $EVAL_ERROR =~ m/No database/ ) { - $stats{execute_no_database}++; - } - } - return $args; - }, - ); - } # execute - } # execute throttle and execute - if ( $o->get('print') ) { my $w = new SlowLogWriter(); $pipeline->add( @@ -14633,7 +14906,6 @@ sub main { instances => [ ($qv_dbh ? { dbh => $qv_dbh, dsn => $review_dsn } : ()), ($ps_dbh ? { dbh => $ps_dbh, dsn => $ps_dsn } : ()), - ($ex_dbh ? { dbh => $ex_dbh, dsn => $ex_dsn } : ()) ], protocol => $o->get('version-check'), ); @@ -14658,13 +14930,15 @@ sub main { } PTDEBUG && _d("Pipeline data:", Dumper($pipeline_data)); + save_resume_offset(); + # Disconnect all open $dbh's map { $dp->disconnect($_); PTDEBUG && _d('Disconnected dbh', $_); } grep { $_ } - ($qv_dbh, $qv_dbh2, $ex_dbh, $ps_dbh, $ep_dbh, $aux_dbh); + ($qv_dbh, $ps_dbh, $ep_dbh, $aux_dbh); return 0; } # End main() @@ -14673,6 +14947,77 @@ sub main { # Subroutines. # ############################################################################ +sub create_review_tables { + my ( %args ) = @_; + my @required_args = qw(dbh full_table TableParser); + foreach my $arg ( @required_args ) { + die "I need a $arg argument" unless $args{$arg}; + } + my $create_table_sql = $args{create_table_sql}; + my ($dbh, $full_table, $tp) = @args{@required_args}; + + PTDEBUG && _d('Checking --review table', $full_table); + + # If the repl db doesn't exit, auto-create it, maybe. + my ($db, $tbl) = Quoter->split_unquote($full_table); + my $show_db_sql = qq{SHOW DATABASES LIKE '$db'}; + PTDEBUG && _d($show_db_sql); + my @db_exists = $dbh->selectrow_array($show_db_sql); + if ( !@db_exists && !$args{create_table} ) { + die "--review database $db does not exist and " + . "--no-create-review-tables was specified. You need " + . "to create the database.\n"; + } + else { + # Even if the db already exists, do this in case it does not exist + # on a slave. + my $create_db_sql + = "CREATE DATABASE IF NOT EXISTS " + . Quoter->quote($db) + . " /* $tool */"; + PTDEBUG && _d($create_db_sql); + eval { + $dbh->do($create_db_sql); + }; + if ( $EVAL_ERROR && !@db_exists ) { + warn $EVAL_ERROR; + die "--review database $db does not exist and it cannot be " + . "created automatically. You need to create the database.\n"; + } + } + + # USE the correct db + my $sql = "USE " . Quoter->quote($db); + PTDEBUG && _d($sql); + $dbh->do($sql); + + # Check if the table exists; if not, create it, maybe. + my $tbl_exists = $tp->check_table( + dbh => $dbh, + db => $db, + tbl => $tbl, + ); + + PTDEBUG && _d('Table exists: ', $tbl_exists ? 'yes' : 'no'); + + if ( !$tbl_exists && !$args{create_table} ) { + die "Table $full_table does not exist and " + . "--no-create-review-tables was specified. " + . "You need to create the table.\n"; + } + else { + PTDEBUG && _d($dbh, $create_table_sql); + eval { + $dbh->do($create_table_sql); + }; + if ( $EVAL_ERROR && !$args{create_table} ) { + warn $EVAL_ERROR; + die "--review history table $full_table does not exist and it cannot be " + . "created automatically. You need to create the table.\n" + } + } +} + # TODO: This sub is poorly named since it does more than print reports: # it aggregates, reports, does QueryReview stuff, etc. sub print_reports { @@ -14691,9 +15036,7 @@ sub print_reports { for my $i ( 0..$#groupby ) { if ( $o->get('report') || $qv ) { - $eas->[$i]->calculate_statistical_metrics( - apdex_t => $o->get('apdex-threshold'), - ); + $eas->[$i]->calculate_statistical_metrics(); } my ($orderby_attrib, $orderby_func) = split(/:/, $orderby[$i]); @@ -14731,19 +15074,18 @@ sub print_reports { $print_header = 1; } - my $qrf = new QueryReportFormatter( - dbh => $ep_dbh, - %args, - ); - # http://code.google.com/p/maatkit/issues/detail?id=1141 - $qrf->set_report_formatter( - report => 'profile', - formatter => new ReportFormatter ( - line_width => $o->get('explain') ? 82 : 74, - long_last_column => 1, - extend_right => 1, - ), + my $report_class = $o->get('output') =~ m/\Ajson\z/i + ? 'JSONReportFormatter' + : 'QueryReportFormatter'; + my $qrf = $report_class->new( + dbh => $ep_dbh, + QueryReview => $args{QueryReview}, + QueryRewriter => $args{QueryRewriter}, + OptionParser => $args{OptionParser}, + QueryParser => $args{QueryParser}, + Quoter => $args{Quoter}, ); + $qrf->print_reports( reports => \@reports, ea => $eas->[$i], @@ -14774,14 +15116,6 @@ sub print_reports { $tls->[$i]->reset_aggregated_data(); } - if ( $o->get('table-access') ) { # --table-access - print_table_access_report( - ea => $eas->[$i], - worst => $worst, - %args, - ); - } - $eas->[$i]->reset_aggregated_data(); # Reset for next iteration. # Print header report only once. So remove it from the @@ -14792,7 +15126,7 @@ sub print_reports { } # Each groupby - if ( $o->get('pipeline-profile') ) { + if ( PTDEBUG ) { my $report = new ReportFormatter( line_width => 74, ); @@ -14801,7 +15135,7 @@ sub print_reports { { name => 'Time', right_justify => 1 }, { name => 'Count', right_justify => 1 }, ); - $report->set_title('Pipeline profile'); + $report->title('Pipeline profile'); my $instrument = $pipeline->instrumentation; my $total_time = $instrument->{Pipeline}; foreach my $process_name ( $pipeline->processes() ) { @@ -14813,51 +15147,12 @@ sub print_reports { # Reset profile for next iteration. $pipeline->reset(); - print "\n" . $report->get_report(); + _d($report->get_report()); } return; } -# Pass in the currently open $dbh (if any), where $current points to ('execute' -# or 'processlist') and whether you want to be connected to the read_only -# server. Get back which server you're looking at, and the $dbh. Assumes that -# one of the servers is ALWAYS read only and the other is ALWAYS not! If -# there's some transition period where this isn't true, maybe both will end up -# pointing to the same place, but that should resolve shortly. -# The magic switching functionality only works if --mirror is given! Otherwise -# it just returns the correct $dbh. $comment is some descriptive text for -# debuggin, like 'for --execute'. -sub find_role { - my ( %args ) = @_; - my $o = $args{OptionParser}; - my $dp = $args{DSNParser}; - my $dbh = $args{dbh}; - my $current = $args{current}; - my $read_only = $args{read_only}; - my $comment = $args{comment}; - - if ( !$dbh || !$dbh->ping ) { - PTDEBUG && _d('Getting a dbh from', $current, $comment); - $dbh = $dp->get_dbh( - $dp->get_cxn_params($o->get($current)), {AutoCommit => 1}); - $dbh->{InactiveDestroy} = 1; # Don't die on fork(). - } - if ( $o->get('mirror') ) { - my ( $is_read_only ) = $dbh->selectrow_array('SELECT @@global.read_only'); - PTDEBUG && _d("read_only on", $current, $comment, ':', - $is_read_only, '(want', $read_only, ')'); - if ( $is_read_only != $read_only ) { - $current = $current eq 'execute' ? 'processlist' : 'execute'; - PTDEBUG && _d("read_only wrong", $comment, "getting a dbh from", $current); - $dbh = $dp->get_dbh( - $dp->get_cxn_params($o->get($current)), {AutoCommit => 1}); - $dbh->{InactiveDestroy} = 1; # Don't die on fork(). - } - } - return ($current, $dbh); -} - # Catches signals so we can exit gracefully. sub sig_int { my ( $signal ) = @_; @@ -14867,6 +15162,7 @@ sub sig_int { } else { print STDERR "# Exiting on SIG$signal.\n"; + save_resume_offset(); exit(1); } } @@ -15006,54 +15302,6 @@ sub get_worst_queries { return $ea->top_events(%top_spec); } -sub print_table_access_report { - my ( %args ) = @_; - my @required_args = qw(ea worst QueryParser QueryRewriter OptionParser Quoter); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless $args{$arg}; - } - my ($ea, $worst, $qp, $qr, $o, $q) = @args{@required_args}; - - my %seen; - PTDEBUG && _d('Doing table access report'); - - foreach my $worst_info ( @$worst ) { - my $item = $worst_info->[0]; - my $stats = $ea->results->{classes}->{$item}; - my $sample = $ea->results->{samples}->{$item}; - my $samp_query = $sample->{arg} || ''; - my ($default_db) = $sample->{db} ? $sample->{db} - : $stats->{db}->{unq} ? keys %{$stats->{db}->{unq}} - : undef; - eval { - QUERY: - foreach my $query ( $qp->split($samp_query) ) { - my $rw = $qp->query_type($query, $qr)->{rw}; - next QUERY unless $rw; - my @tables = $qp->extract_tables( - query => $query, - default_db => $default_db, - Quoter => $args{Quoter}, - ); - next QUERY unless scalar @tables; - DB_TBL: - foreach my $tbl_info ( @tables ) { - my ($db, $tbl) = @$tbl_info; - $db = $db ? "`$db`." : ''; - next DB_TBL if $seen{"$db$tbl"}++; # Unique-ify for issue 337. - print "$rw $db`$tbl`\n"; - } - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d($EVAL_ERROR); - warn "Cannot get table access for query $_"; - } - } - - return; -} - sub update_query_review_tables { my ( %args ) = @_; foreach my $arg ( qw(ea worst QueryReview OptionParser) ) { @@ -15079,17 +15327,15 @@ sub update_query_review_tables { first_seen => $stats->{ts}->{min}, last_seen => $stats->{ts}->{max} ); - if ( $o->get('review-history') ) { - my %history; - foreach my $attrib ( @$attribs ) { - $history{$attrib} = $ea->metrics( - attrib => $attrib, - where => $item, - ); - } - $qv->set_review_history( - $item, $sample->{arg} || '', %history); + my %history; + foreach my $attrib ( @$attribs ) { + $history{$attrib} = $ea->metrics( + attrib => $attrib, + where => $item, + ); } + $qv->set_review_history( + $item, $sample->{arg} || '', %history); } return; @@ -15160,6 +15406,23 @@ sub verify_run_time { return $boundary; } +sub save_resume_offset { + if ( !$resume_file || !$offset ) { + PTDEBUG && _d('Not saving resume offset because there is no ' + . 'resume file or offset:', $resume_file, $offset); + return; + } + + PTDEBUG && _d('Saving resume at offset', $offset, 'to', $resume_file); + open my $resume_fh, '>', $resume_file + or die "Error opening $resume_file: $OS_ERROR"; + print { $resume_fh } $offset, "\n"; + close $resume_fh + or die "Error close $resume_file: $OS_ERROR"; + warn "\n# Saved resume file offset $offset to $resume_file\n"; + return; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -15199,13 +15462,8 @@ Analyze, aggregate, and report on a slow query log: Review a slow log, saving results to the test.query_review table in a MySQL server running on host1. See L<"--review"> for more on reviewing queries: - pt-query-digest --review h=host1,D=test,t=query_review /path/to/slow.log - -Filter out everything but SELECT queries, replay the queries against another -server, then use the timings from replaying them to analyze their performance: - - pt-query-digest /path/to/slow.log --execute h=another_server \ - --filter '$event->{fingerprint} =~ m/^select/' + pt-query-digest --review h=host1 --review-table test.query_review + --history-table test.query_history /path/to/slow.log Print the structure of events so you can construct a complex L<"--filter">: @@ -15235,8 +15493,7 @@ is safe to run even on production systems, but you might want to monitor it until you are satisfied that the input you give it does not cause undue load. Various options will cause pt-query-digest to insert data into tables, execute -SQL queries, and so on. These include the L<"--execute"> option and -L<"--review">. +SQL queries, and so on. These include the L<"--review"> option. At the time of this release, we know of no bugs that could cause serious harm to users. @@ -15345,9 +15602,7 @@ that follows. It contains the following columns: Response time The total response time, and percentage of overall total Calls The number of times this query was executed R/Call The mean response time per execution - Apdx The Apdex score; see --apdex-threshold for details V/M The Variance-to-mean ratio of response time - EXPLAIN If --explain was specified, a sparkline; see --explain Item The distilled query A final line whose rank is shown as MISC contains aggregate statistics on the @@ -15461,12 +15716,6 @@ above, and something like the following: See also L<"--report-format">. -=head2 SPARKLINES - -The output also contains sparklines. Sparklines are "data-intense, -design-simple, word-sized graphics" (L).There is a sparkline for L<"--report-histogram"> and for L<"--explain">. -See each of those options for details about interpreting their sparklines. - =head1 QUERY REVIEWS A "query review" is the process of storing all the query fingerprints analyzed. @@ -15531,9 +15780,9 @@ example, You can see how useful this meta-data is -- as you analyze your queries, you get your comments integrated right into the report. -If you add the L<"--review-history"> option, it will also store information into -a separate database table, so you can keep historical trending information on -classes of queries. +The tool will also store information into a separate database table specified +by the L<"--history-table"> option, so you can keep historical trending information +on classes of queries. =back @@ -15637,27 +15886,11 @@ Collapse multiple identical UNION queries into a single one. =head1 OPTIONS -DSN values in L<"--review-history"> default to values in L<"--review"> if COPY -is yes. - This tool accepts additional command-line arguments. Refer to the L<"SYNOPSIS"> and usage information for details. =over -=item --apdex-threshold - -type: float; default: 1.0 - -Set Apdex target threshold (T) for query response time. The Application -Performance Index (Apdex) Technical Specification V1.1 defines T as "a -positive decimal value in seconds, having no more than two significant digits -of granularity." This value only applies to query response time (Query_time). - -Options can be abbreviated so specifying C<--apdex-t> also works. - -See L. - =item --ask-pass Prompt for a password when connecting to MySQL. @@ -15737,21 +15970,19 @@ first option on the command line. default: yes -Continue parsing even if there is an error. +Continue parsing even if there is an error. The tool will not continue +forever: it stops once any process causes 100 errors, in which case there +is probably a bug in the tool or the input is invalid. -=item --create-review-history-table +=item --[no]create-review-tables -Create the L<"--review-history"> table if it does not exist. +default: yes -This option causes the table specified by L<"--review-history"> to be created -with the default structure shown in the documentation for that option. +Create the L<"--review"> tables if they do not exist. -=item --create-review-table - -Create the L<"--review"> table if it does not exist. - -This option causes the table specified by L<"--review"> to be created with the -default structure shown in the documentation for that option. +This option causes the tables specified by L<"--review-table"> and +L<"--history-table"> to be created with the default structures shown +in the documentation for L<"--review">. =item --daemonize @@ -15797,50 +16028,6 @@ The second one splits it into attribute-value pairs and adds them to the event: B: All commas in the regex patterns must be escaped with \ otherwise the pattern will break. -=item --execute - -type: DSN - -Execute queries on this DSN. - -Adds a callback into the chain, after filters but before the reports. Events -are executed on this DSN. If they are successful, the time they take to execute -overwrites the event's Query_time attribute and the original Query_time value -(from the log) is saved as the Exec_orig_time attribute. If unsuccessful, -the callback returns false and terminates the chain. - -If the connection fails, pt-query-digest tries to reconnect once per second. - -See also L<"--mirror"> and L<"--execute-throttle">. - -=item --execute-throttle - -type: array - -Throttle values for L<"--execute">. - -By default L<"--execute"> runs without any limitations or concerns for the -amount of time that it takes to execute the events. The L<"--execute-throttle"> -allows you to limit the amount of time spent doing L<"--execute"> relative -to the other processes that handle events. This works by marking some events -with a C attribute when L<"--execute"> begins to take too much time. -L<"--execute"> will not execute an event if this attribute is true. This -indirectly decreases the time spent doing L<"--execute">. - -The L<"--execute-throttle"> option takes at least two comma-separated values: -max allowed L<"--execute"> time as a percentage and a check interval time. An -optional third value is a percentage step for increasing and decreasing the -probability that an event will be marked C true. 5 (percent) is -the default step. - -For example: L<"--execute-throttle"> C<70,60,10>. This will limit -L<"--execute"> to 70% of total event processing time, checked every minute -(60 seconds) and probability stepped up and down by 10%. When L<"--execute"> -exceeds 70%, the probability that events will be marked C true -increases by 10%. L<"--execute"> time is checked again after another minute. -If it's still above 70%, then the probability will increase another 10%. -Or, if it's dropped below 70%, then the probability will decrease by 10%. - =item --expected-range type: array; default: 5,10 @@ -15865,41 +16052,10 @@ be EXPLAINed. Those are typically "derived table" queries of the form select ... from ( select .... ) der; -The EXPLAIN results are printed in three places: a sparkline in the event -header, a full vertical format in the event report, and a sparkline in the -profile. - -The full format appears at the end of each event report in vertical style +The EXPLAIN results are printed as a full vertical format in the event report, +which appears at the end of each event report in vertical style (C<\G>) just like MySQL prints it. -The sparklines (see L<"SPARKLINES">) are compact representations of the -access type for each table and whether or not "Using temporary" or "Using -filesort" appear in EXPLAIN. The sparklines look like: - - nr>TF - -That sparkline means that there are two tables, the first uses a range (n) -access, the second uses a ref access, and both "Using temporary" (T) and -"Using filesort" (F) appear. The greater-than character just separates table -access codes from T and/or F. - -The abbreviated table access codes are: - - a ALL - c const - e eq_ref - f fulltext - i index - m index_merge - n range - o ref_or_null - r ref - s system - u unique_subquery - -A capitalized access code means that "Using index" appears in EXPLAIN for -that table. - =item --filter type: string @@ -15989,22 +16145,6 @@ check both. Since L<"--filter"> allows you to alter C<$event>, you can use it to do other things, like create new attributes. See L<"ATTRIBUTES"> for an example. -=item --fingerprints - -Add query fingerprints to the standard query analysis report. This is mostly -useful for debugging purposes. - -=item --[no]for-explain - -default: yes - -Print extra information to make analysis easy. - -This option adds code snippets to make it easy to run SHOW CREATE TABLE and SHOW -TABLE STATUS for the query's tables. It also rewrites non-SELECT queries into a -SELECT that might be helpful for determining the non-SELECT statement's index -usage. - =item --group-by type: Array; default: fingerprint @@ -16060,6 +16200,12 @@ L<"ATTRIBUTES">). Show help and exit. +=item --history-table + +type: string; default: percona_schema.query_history + +Where to save the historical data produced by L<"--review">. + =item --host short form: -h; type: string @@ -16089,10 +16235,6 @@ which do not have them. For example, if one event has the db attribute equal to "foo", but the next event doesn't have the db attribute, then it inherits "foo" for its db attribute. -Inheritance is usually desirable, but in some cases it might confuse things. -If a query inherits a database that it doesn't actually use, then this could -confuse L<"--execute">. - =item --interval type: float; default: .1 @@ -16135,20 +16277,6 @@ type: string Print all output to this file when daemonized. -=item --mirror - -type: float - -How often to check whether connections should be moved, depending on -C. Requires L<"--processlist"> and L<"--execute">. - -This option causes pt-query-digest to check every N seconds whether it is reading -from a read-write server and executing against a read-only server, which is a -sensible way to set up two servers if you're doing something like master-master -replication. The L master-master -toolkit does this. The aim is to keep the passive server ready for failover, -which is impossible without putting it under a realistic workload. - =item --order-by type: Array; default: Query_time:sum @@ -16208,6 +16336,13 @@ seconds and which are seen at least 5 times, use the following argument: You can specify an --outliers option for each value in L<"--group-by">. + +=item --output + +type: string; default: query + +Type of report to use. Accepted values are C<"query"> and C<"json">. + =item --password short form: -p; type: string @@ -16224,10 +16359,6 @@ daemonized instance exits. The program checks for the existence of the PID file when starting; if it exists and the process with the matching PID exists, the program exits. -=item --pipeline-profile - -Print a profile of the pipeline processes. - =item --port short form: -P; type: int @@ -16256,8 +16387,7 @@ type: DSN Poll this DSN's processlist for queries, with L<"--interval"> sleep between. -If the connection fails, pt-query-digest tries to reopen it once per second. See -also L<"--mirror">. +If the connection fails, pt-query-digest tries to reopen it once per second. =item --progress @@ -16338,36 +16468,35 @@ like: # 1s ######## # 10s+ -A sparkline (see L<"SPARKLINES">) of the full chart is also printed in the -header for each query event. The sparkline of that full chart is: - - # Query_time sparkline: | .^_ | - -The sparkline itself is the 8 characters between the pipes (C<|>), one character -for each of the 8 buckets (1us, 10us, etc.) Four character codes are used -to represent the approximate relation between each bucket's value: - - _ . - ^ - -The caret C<^> represents peaks (buckets with the most values), and -the underscore C<_> represents lows (buckets with the least or at least -one value). The period C<.> and the hyphen C<-> represent buckets with values -between these two extremes. If a bucket has no values, a space is printed. -So in the example above, the period represents the 10ms bucket, the caret -the 100ms bucket, and the underscore the 1s bucket. - See L<"OUTPUT"> for more information. +=item --resume + +type: string + +If specified, the tool writes the last file offset, if there is one, +to the given filename. When ran again with the same value for this option, +the tool reads the last file offset from the file, seeks to that position +in the log, and resumes parsing events from that point onward. + =item --review type: DSN -Store a sample of each class of query in this DSN. +Store a sample of each class of query in this DSN, plus historical values +for review trend analysis -The argument specifies a table to store all unique query fingerprints in. The -table must have at least the following columns. You can add more columns for -your own special purposes, but they won't be used by pt-query-digest. The -following CREATE TABLE definition is also used for L<"--create-review-table">. +The argument specifies a host to store all unique query fingerprints in; the +databases and tables were this data is stored can be specified with the +L<"--review-table"> and L<"--history-table"> options. +By default, if the table doesn't exist the tool mtries creating it; This +behavior can bhe controlled with the L<"--[no]create-review-tables"> option. +If the table was created manually, it must have at least the following columns. +You can add more columns for your own special purposes, but they won't be used +by pt-query-digest. The following CREATE TABLE definition is also used by +L<"--no-create-review-tables">. + +=for comment ignore-pt-internal-value MAGIC_create_review: CREATE TABLE query_review ( @@ -16402,23 +16531,12 @@ After parsing and aggregating events, your table should contain a row for each fingerprint. This option depends on C<--group-by fingerprint> (which is the default). It will not work otherwise. -=item --review-history -type: DSN +Additionally, pt-query-digest will save historical information into a review table, +so you can see how classes of queries have changed over time. You can +change the destination table with the L<"--history-table"> -The table in which to store historical values for review trend analysis. - -Each time you review queries with L<"--review">, pt-query-digest will save -information into this table so you can see how classes of queries have changed -over time. - -This DSN inherits unspecified values from L<"--review">. It should mention a -table in which to store statistics about each class of queries. pt-query-digest -verifies the existence of the table, and your privileges to insert, delete and -update on that table. - -pt-query-digest then inspects the columns in the table. The table must have at -least the following columns: +The table must have at least the following columns: CREATE TABLE query_review_history ( checksum BIGINT UNSIGNED NOT NULL, @@ -16427,7 +16545,10 @@ least the following columns: Any columns not mentioned above are inspected to see if they follow a certain naming convention. The column is special if the name ends with an underscore -followed by any of these MAGIC_history_cols values: +followed by any of these values: + +=for comment ignore-pt-internal-value +MAGIC_history_cols pct|avt|cnt|sum|min|max|pct_95|stddev|median|rank @@ -16443,8 +16564,11 @@ columns and making them part of the primary key along with the checksum. But you could also just add a ts_min column and make it a DATE type, so you'd get one row per class of queries per day. -The default table structure follows. The following MAGIC_create_review_history -table definition is used for L<"--create-review-history-table">: +The default table structure follows. The following table definition is used +for L<"--[no]create-review-tables">: + +=for comment ignore-pt-internal-value +MAGIC_create_review_history CREATE TABLE query_review_history ( checksum BIGINT UNSIGNED NOT NULL, @@ -16550,6 +16674,12 @@ table definition is used for L<"--create-review-history-table">: Note that we store the count (cnt) for the ts attribute only; it will be redundant to store this for other attributes. +=item --review-table + +type: string; default: percona_schema.query_review + +Where to save the samples produced by L<"--review">. + =item --run-time type: time @@ -16652,7 +16782,7 @@ Previously, pt-query-digest only aggregated these attributes: Query_time,Lock_time,Rows_sent,Rows_examined,user,db:Schema,ts -Attributes specified in the L<"--review-history"> table will always be selected +Attributes in the table specified by L<"--history-table"> will always be selected even if you do not specify L<"--select">. See also L<"--ignore-attributes"> and L<"ATTRIBUTES">. @@ -16714,9 +16844,9 @@ several types: CURRENT_DATE - INTERVAL 7 DAY If you give a MySQL time expression, then you must also specify a DSN -so that pt-query-digest can connect to MySQL to evaluate the expression. If you -specify L<"--execute">, L<"--explain">, L<"--processlist">, L<"--review"> -or L<"--review-history">, then one of these DSNs will be used automatically. +so that pt-query-digest can connect to MySQL to evaluate the expression. +If you specify L<"--explain">, L<"--processlist">, L<"--review">, then +one of these DSNs will be used automatically. Otherwise, you must specify an L<"--aux-dsn"> or pt-query-digest will die saying that the value is invalid. @@ -16739,59 +16869,6 @@ short form: -S; type: string Socket file to use for connection. -=item --statistics - -Print statistics about internal counters. This option is mostly for -development and debugging. The statistics report is printed for each -iteration after all other reports, even if no events are processed or -C<--no-report> is specified. The statistics report looks like: - - # No events processed. - - # Statistic Count %/Events - # ================================================ ====== ======== - # events_read 142030 100.00 - # events_parsed 50430 35.51 - # events_aggregated 0 0.00 - # ignored_midstream_server_response 18111 12.75 - # no_tcp_data 91600 64.49 - # pipeline_restarted_after_MemcachedProtocolParser 142030 100.00 - # pipeline_restarted_after_TcpdumpParser 1 0.00 - # unknown_client_command 1 0.00 - # unknown_client_data 32318 22.75 - -The first column is the internal counter name; the second column is counter's -count; and the third column is the count as a percentage of C. - -In this case, it shows why no events were processed/aggregated: 100% of events -were rejected by the C. Of those, 35.51% were data -packets, but of these 12.75% of ignored mid-stream server response, one was -an unknown client command, and 22.75% were unknown client data. The other -64.49% were TCP control packets (probably most ACKs). - -Since pt-query-digest is complex, you will probably need someone familiar -with its code to decipher the statistics report. - -=item --table-access - -Print a table access report. - -The table access report shows which tables are accessed by all the queries -and if the access is a read or write. The report looks like: - - write `baz`.`tbl` - read `baz`.`new_tbl` - write `baz`.`tbl3` - write `db6`.`tbl6` - -If you pipe the output to L, the read and write tables will be grouped -together and sorted alphabetically: - - read `baz`.`new_tbl` - write `baz`.`tbl` - write `baz`.`tbl3` - write `db6`.`tbl6` - =item --tcpdump-errors type: string @@ -17089,7 +17166,8 @@ Default character set. dsn: database; copy: yes -Database that contains the query review table. +Default database for the review option. Only useful if there are replication +filters set up. =item * F @@ -17123,7 +17201,7 @@ Socket file to use for connection. =item * t -Table to use as the query review table. +Not used. =item * u @@ -17405,8 +17483,7 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2008-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2008-2013 Percona Ireland Ltd. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -17424,6 +17501,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-query-digest 2.1.7 +pt-query-digest 2.1.8 =cut diff --git a/bin/pt-show-grants b/bin/pt-show-grants index 1854f2d4..3f318ecd 100755 --- a/bin/pt-show-grants +++ b/bin/pt-show-grants @@ -2285,8 +2285,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -2304,6 +2304,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-show-grants 2.1.7 +pt-show-grants 2.1.8 =cut diff --git a/bin/pt-sift b/bin/pt-sift index 539af395..16df99ac 100755 --- a/bin/pt-sift +++ b/bin/pt-sift @@ -587,7 +587,7 @@ main() { # Execute the program if it was not included from another file. This makes it # possible to include without executing, and thus test. if [ "${0##*/}" = "$TOOL" ] \ - || [ "${0##*/}" = "bash" -a "$_" = "$0" ]; then + || [ "${0##*/}" = "bash" -a "${_:-""}" = "$0" ]; then main "${@:-""}" fi @@ -762,8 +762,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2010-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -781,7 +781,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-sift 2.1.7 +pt-sift 2.1.8 =cut diff --git a/bin/pt-slave-delay b/bin/pt-slave-delay index e3de0762..5f4daf70 100755 --- a/bin/pt-slave-delay +++ b/bin/pt-slave-delay @@ -15,12 +15,15 @@ BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit OptionParser - Mo + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo DSNParser Daemon Transformers Retry - VersionCheck HTTPMicro Pingback )); @@ -36,7 +39,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -1070,18 +1073,24 @@ if ( PTDEBUG ) { # ########################################################################### # ########################################################################### -# Mo package +# Lmo::Utils package # This package is a copy without comments from the original. The original # with comments and its test file can be found in the Bazaar repository at, -# lib/Mo.pm -# t/lib/Mo.t +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t # See https://launchpad.net/percona-toolkit for more information. # ########################################################################### { +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} { no strict 'refs'; @@ -1094,6 +1103,194 @@ our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. } } +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + use strict; use warnings qw( FATAL all ); @@ -1115,240 +1312,277 @@ our %TYPES = ( } qw(Array Code Hash Regexp Glob Scalar) ); -our %metadata_for; -{ - package Mo::Object; +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; } - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; } - else { - $ref = { @_ }; - } - return $ref; + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); } } +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + my %export_for; -sub Mo::import { - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); +sub import { + warnings->import(qw(FATAL all)); + strict->import(); - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; } - } - return if $exports{M}; + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; + goto &$original_method + }; + } - $metadata_for{$caller}{$attribute} = (); - - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) } - }, - %exports, - ); + goto &$original_method; + } + } - $export_for{$caller} = [ keys %exports ]; + _install_coderef "${caller}::$attribute" => $method; - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } } sub _has_handles { @@ -1370,8 +1604,8 @@ sub _has_handles { $kv = { map { $_, $_ } grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } keys %{ _stash_for $target_class } }; } @@ -1397,80 +1631,32 @@ sub _has_handles { } } -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $inner_types = _nested_constraints($1, $2); - } - else { - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - return 1 if ! defined($value); - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - sub _set_package_isa { my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; } sub _set_inherited_metadata { my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); my $linearized_isa = mro::get_linear_isa($class); my %new_metadata; for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); %new_metadata = ( %new_metadata, - %{ $metadata_for{$isa_class} || {} }, + %$isa_metadata, ); } - $metadata_for{$class} = \%new_metadata; + %$class_metadata = %new_metadata; } sub unimport { my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); } sub Dumper { @@ -1513,11 +1699,21 @@ BEGIN { } } +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + } 1; } # ########################################################################### -# End Mo package +# End Lmo package # ########################################################################### # ########################################################################### @@ -2119,24 +2315,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -2268,6 +2466,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -2525,300 +2726,6 @@ sub _d { # End Retry package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -3508,7 +3415,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -3584,10 +3490,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -3598,13 +3503,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -3634,7 +3539,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -3817,6 +3722,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -4578,9 +4727,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Sergey Zhuravle and Baron Schwartz, -2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Sergey Zhuravle and Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -4598,6 +4746,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-slave-delay 2.1.7 +pt-slave-delay 2.1.8 =cut diff --git a/bin/pt-slave-find b/bin/pt-slave-find index d1b5c6f1..d104a4d6 100755 --- a/bin/pt-slave-find +++ b/bin/pt-slave-find @@ -14,7 +14,11 @@ use warnings FATAL => 'all'; BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( OptionParser - Mo + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo DSNParser MasterSlave Daemon @@ -1049,18 +1053,24 @@ if ( PTDEBUG ) { # ########################################################################### # ########################################################################### -# Mo package +# Lmo::Utils package # This package is a copy without comments from the original. The original # with comments and its test file can be found in the Bazaar repository at, -# lib/Mo.pm -# t/lib/Mo.t +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t # See https://launchpad.net/percona-toolkit for more information. # ########################################################################### { +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} { no strict 'refs'; @@ -1073,6 +1083,194 @@ our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. } } +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + use strict; use warnings qw( FATAL all ); @@ -1094,240 +1292,277 @@ our %TYPES = ( } qw(Array Code Hash Regexp Glob Scalar) ); -our %metadata_for; -{ - package Mo::Object; +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; } - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; } - else { - $ref = { @_ }; - } - return $ref; + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); } } +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + my %export_for; -sub Mo::import { - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); +sub import { + warnings->import(qw(FATAL all)); + strict->import(); - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; } - } - return if $exports{M}; + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; + goto &$original_method + }; + } - $metadata_for{$caller}{$attribute} = (); - - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) } - }, - %exports, - ); + goto &$original_method; + } + } - $export_for{$caller} = [ keys %exports ]; + _install_coderef "${caller}::$attribute" => $method; - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } } sub _has_handles { @@ -1349,8 +1584,8 @@ sub _has_handles { $kv = { map { $_, $_ } grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } keys %{ _stash_for $target_class } }; } @@ -1376,80 +1611,32 @@ sub _has_handles { } } -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $inner_types = _nested_constraints($1, $2); - } - else { - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - return 1 if ! defined($value); - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - sub _set_package_isa { my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; } sub _set_inherited_metadata { my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); my $linearized_isa = mro::get_linear_isa($class); my %new_metadata; for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); %new_metadata = ( %new_metadata, - %{ $metadata_for{$isa_class} || {} }, + %$isa_metadata, ); } - $metadata_for{$class} = \%new_metadata; + %$class_metadata = %new_metadata; } sub unimport { my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); } sub Dumper { @@ -1492,11 +1679,21 @@ BEGIN { } } +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + } 1; } # ########################################################################### -# End Mo package +# End Lmo package # ########################################################################### # ########################################################################### @@ -2823,7 +3020,7 @@ sub _d { { package VersionParser; -use Mo; +use Lmo; use Scalar::Util qw(blessed); use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -2999,7 +3196,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } -no Mo; +no Lmo; 1; } # ########################################################################### @@ -3026,24 +3223,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -3175,6 +3374,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -4003,8 +4205,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -4022,6 +4224,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-slave-find 2.1.7 +pt-slave-find 2.1.8 =cut diff --git a/bin/pt-slave-restart b/bin/pt-slave-restart index 5ea55372..c0362677 100755 --- a/bin/pt-slave-restart +++ b/bin/pt-slave-restart @@ -16,12 +16,15 @@ BEGIN { Percona::Toolkit Quoter OptionParser - Mo + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo VersionParser DSNParser MasterSlave Daemon - VersionCheck HTTPMicro Pingback )); @@ -37,7 +40,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -1197,18 +1200,24 @@ if ( PTDEBUG ) { # ########################################################################### # ########################################################################### -# Mo package +# Lmo::Utils package # This package is a copy without comments from the original. The original # with comments and its test file can be found in the Bazaar repository at, -# lib/Mo.pm -# t/lib/Mo.t +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t # See https://launchpad.net/percona-toolkit for more information. # ########################################################################### { +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} { no strict 'refs'; @@ -1221,6 +1230,194 @@ our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. } } +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + use strict; use warnings qw( FATAL all ); @@ -1242,240 +1439,277 @@ our %TYPES = ( } qw(Array Code Hash Regexp Glob Scalar) ); -our %metadata_for; -{ - package Mo::Object; +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; } - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; } - else { - $ref = { @_ }; - } - return $ref; + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); } } +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + my %export_for; -sub Mo::import { - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); +sub import { + warnings->import(qw(FATAL all)); + strict->import(); - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; } - } - return if $exports{M}; + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; + goto &$original_method + }; + } - $metadata_for{$caller}{$attribute} = (); - - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) } - }, - %exports, - ); + goto &$original_method; + } + } - $export_for{$caller} = [ keys %exports ]; + _install_coderef "${caller}::$attribute" => $method; - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } } sub _has_handles { @@ -1497,8 +1731,8 @@ sub _has_handles { $kv = { map { $_, $_ } grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } keys %{ _stash_for $target_class } }; } @@ -1524,80 +1758,32 @@ sub _has_handles { } } -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $inner_types = _nested_constraints($1, $2); - } - else { - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - return 1 if ! defined($value); - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - sub _set_package_isa { my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; } sub _set_inherited_metadata { my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); my $linearized_isa = mro::get_linear_isa($class); my %new_metadata; for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); %new_metadata = ( %new_metadata, - %{ $metadata_for{$isa_class} || {} }, + %$isa_metadata, ); } - $metadata_for{$class} = \%new_metadata; + %$class_metadata = %new_metadata; } sub unimport { my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); } sub Dumper { @@ -1640,11 +1826,21 @@ BEGIN { } } +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + } 1; } # ########################################################################### -# End Mo package +# End Lmo package # ########################################################################### # ########################################################################### @@ -1658,7 +1854,7 @@ BEGIN { { package VersionParser; -use Mo; +use Lmo; use Scalar::Util qw(blessed); use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -1834,7 +2030,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } -no Mo; +no Lmo; 1; } # ########################################################################### @@ -3154,300 +3350,6 @@ sub _d { # End Daemon package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -4137,7 +4039,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -4213,10 +4114,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -4227,13 +4127,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -4263,7 +4163,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -4446,6 +4346,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -5500,8 +5644,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -5519,6 +5663,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-slave-restart 2.1.7 +pt-slave-restart 2.1.8 =cut diff --git a/bin/pt-stalk b/bin/pt-stalk index 754ba671..8adbd5bc 100755 --- a/bin/pt-stalk +++ b/bin/pt-stalk @@ -22,23 +22,32 @@ PTFUNCNAME="" PTDEBUG="${PTDEBUG:-""}" EXIT_STATUS=0 -log() { - TS=$(date +%F-%T | tr ':-' '_'); +ts() { + TS=$(date +%F-%T | tr ':-' '_') echo "$TS $*" } +info() { + [ ${OPT_VERBOSE:-3} -ge 3 ] && ts "$*" +} + +log() { + [ ${OPT_VERBOSE:-3} -ge 2 ] && ts "$*" +} + warn() { - log "$*" >&2 + [ ${OPT_VERBOSE:-3} -ge 1 ] && ts "$*" >&2 EXIT_STATUS=1 } die() { - warn "$*" + ts "$*" >&2 + EXIT_STATUS=1 exit 1 } _d () { - [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(log "$*")" >&2 + [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(ts "$*")" >&2 } # ########################################################################### @@ -71,7 +80,7 @@ PO_DIR="" # Directory with program option spec files usage() { local file="$1" - local usage=$(grep '^Usage: ' "$file") + local usage="$(grep '^Usage: ' "$file")" echo $usage echo echo "For more information, 'man $TOOL' or 'perldoc $file'." @@ -962,6 +971,10 @@ after_collect_sleep() { : } +after_interval_sleep() { + : +} + after_stalk() { : } @@ -1066,9 +1079,7 @@ sleep_ok() { local seconds="$1" local msg="${2:-""}" if oktorun; then - if [ -n "$msg" ]; then - log "$msg" - fi + [ "$msg" ] && info "$msg" sleep $seconds fi } @@ -1126,7 +1137,11 @@ stalk() { fi local msg="Check results: $OPT_VARIABLE=$value, matched=${matched:-no}, cycles_true=$cycles_true" - log "$msg" + if [ "$matched" ]; then + log "$msg" + else + info "$msg" + fi elif [ "$OPT_COLLECT" ]; then # Make the next if condition true. matched=1 @@ -1140,7 +1155,7 @@ stalk() { # ################################################################## # Start collecting, maybe. # ################################################################## - log "Collect triggered" + log "Collect $ITER triggered" # Send email to whomever that collect has been triggered. if [ "$OPT_NOTIFY_BY_EMAIL" ]; then @@ -1166,8 +1181,8 @@ stalk() { "$margin" if [ $? -eq 0 ]; then # There should be enough disk space, so collect. - log "$msg" >> "$OPT_DEST/$prefix-trigger" - log "pt-stalk ran with $RAN_WITH" >> "$OPT_DEST/$prefix-trigger" + ts "$msg" >> "$OPT_DEST/$prefix-trigger" + ts "pt-stalk ran with $RAN_WITH" >> "$OPT_DEST/$prefix-trigger" last_prefix="$prefix" # Plugin hook: @@ -1181,7 +1196,7 @@ stalk() { collect "$OPT_DEST" "$prefix" ) >> "$OPT_DEST/$prefix-output" 2>&1 & local collector_pid=$! - log "Collector PID $collector_pid" + log "Collect $ITER PID $collector_pid" # Plugin hook: after_collect $collector_pid @@ -1199,6 +1214,7 @@ stalk() { # ################################################################## # Done collecting. # ################################################################## + log "Collect $ITER done" ITER=$((ITER + 1)) cycles_true=0 sleep_ok "$OPT_SLEEP" "Sleeping $OPT_SLEEP seconds after collect" @@ -1208,6 +1224,9 @@ stalk() { else # Trigger/check/value is ok, sleep until next check. sleep_ok "$OPT_INTERVAL" + + # Plugin hook: + after_interval_sleep fi done @@ -1291,7 +1310,7 @@ main() { # Execute the program if it was not included from another file. # This makes it possible to include without executing, and thus test. if [ "${0##*/}" = "$TOOL" ] \ - || [ "${0##*/}" = "bash" -a "$_" = "$0" ]; then + || [ "${0##*/}" = "bash" -a "${_:-""}" = "$0" ]; then # Parse command line options. We must do this first so we can # see if --daemonize was specified. @@ -1737,6 +1756,10 @@ C. Called after sleeping L<"--sleep"> seconds for the collector process to finish. This hook is called after C. +=item after_interval_sleep + +Called after sleeping L<"--interval"> seconds after each trigger check. + =item after_stalk Called after stalking. Since pt-stalk stalks forever by default, @@ -1840,6 +1863,22 @@ type: string; default: Threads_running The variable to compare against the threshold. See L<"--function"> for details. +=item --verbose + +type: int; default: 2 + +Print more or less information while running. Since the tool is designed +to be a long-running daemon, the default verbosity level only prints the +most important information. If you run the tool interactively, you may +want to use a higher verbosity level. + + LEVEL PRINTS + ===== ===================================== + 0 Errors + 1 Warnings + 2 Matching triggers and collection info + 3 Non-matching triggers + =item --version Print tool's version and exit. @@ -1965,8 +2004,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2010-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -1984,7 +2023,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-stalk 2.1.7 +pt-stalk 2.1.8 =cut diff --git a/bin/pt-summary b/bin/pt-summary index 9bdd2f79..32e864b7 100755 --- a/bin/pt-summary +++ b/bin/pt-summary @@ -29,23 +29,32 @@ PTFUNCNAME="" PTDEBUG="${PTDEBUG:-""}" EXIT_STATUS=0 -log() { - TS=$(date +%F-%T | tr ':-' '_'); +ts() { + TS=$(date +%F-%T | tr ':-' '_') echo "$TS $*" } +info() { + [ ${OPT_VERBOSE:-3} -ge 3 ] && ts "$*" +} + +log() { + [ ${OPT_VERBOSE:-3} -ge 2 ] && ts "$*" +} + warn() { - log "$*" >&2 + [ ${OPT_VERBOSE:-3} -ge 1 ] && ts "$*" >&2 EXIT_STATUS=1 } die() { - warn "$*" + ts "$*" >&2 + EXIT_STATUS=1 exit 1 } _d () { - [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(log "$*")" >&2 + [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(ts "$*")" >&2 } # ########################################################################### @@ -78,7 +87,7 @@ PO_DIR="" # Directory with program option spec files usage() { local file="$1" - local usage=$(grep '^Usage: ' "$file") + local usage="$(grep '^Usage: ' "$file")" echo $usage echo echo "For more information, 'man $TOOL' or 'perldoc $file'." @@ -2280,7 +2289,7 @@ sigtrap() { local PTFUNCNAME=sigtrap; # Execute the program if it was not included from another file. This makes it # possible to include without executing, and thus test. if [ "${0##*/}" = "$TOOL" ] \ - || [ "${0##*/}" = "bash" -a "$_" = "$0" ]; then + || [ "${0##*/}" = "bash" -a "${_:-""}" = "$0" ]; then # Set up temporary dir. mk_tmpdir @@ -2654,8 +2663,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2010-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -2673,7 +2682,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-summary 2.1.7 +pt-summary 2.1.8 =cut diff --git a/bin/pt-table-checksum b/bin/pt-table-checksum index d688bee4..68c7fb3a 100755 --- a/bin/pt-table-checksum +++ b/bin/pt-table-checksum @@ -14,12 +14,15 @@ use warnings FATAL => 'all'; BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit - VersionCheck HTTPMicro Pingback DSNParser OptionParser - Mo + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo Cxn Percona::XtraDB::Cluster Quoter @@ -53,7 +56,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -61,300 +64,6 @@ our $VERSION = '2.1.7'; # End Percona::Toolkit package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -1044,7 +753,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -1120,10 +828,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -1134,13 +841,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -1170,7 +877,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -1353,6 +1060,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -2770,18 +2721,24 @@ if ( PTDEBUG ) { # ########################################################################### # ########################################################################### -# Mo package +# Lmo::Utils package # This package is a copy without comments from the original. The original # with comments and its test file can be found in the Bazaar repository at, -# lib/Mo.pm -# t/lib/Mo.t +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t # See https://launchpad.net/percona-toolkit for more information. # ########################################################################### { +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} { no strict 'refs'; @@ -2794,6 +2751,194 @@ our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. } } +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + use strict; use warnings qw( FATAL all ); @@ -2815,240 +2960,277 @@ our %TYPES = ( } qw(Array Code Hash Regexp Glob Scalar) ); -our %metadata_for; -{ - package Mo::Object; +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; } - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; } - else { - $ref = { @_ }; - } - return $ref; + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); } } +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + my %export_for; -sub Mo::import { - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); +sub import { + warnings->import(qw(FATAL all)); + strict->import(); - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; } - } - return if $exports{M}; + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; + goto &$original_method + }; + } - $metadata_for{$caller}{$attribute} = (); - - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) } - }, - %exports, - ); + goto &$original_method; + } + } - $export_for{$caller} = [ keys %exports ]; + _install_coderef "${caller}::$attribute" => $method; - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } } sub _has_handles { @@ -3070,8 +3252,8 @@ sub _has_handles { $kv = { map { $_, $_ } grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } keys %{ _stash_for $target_class } }; } @@ -3097,80 +3279,32 @@ sub _has_handles { } } -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $inner_types = _nested_constraints($1, $2); - } - else { - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - return 1 if ! defined($value); - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - sub _set_package_isa { my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; } sub _set_inherited_metadata { my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); my $linearized_isa = mro::get_linear_isa($class); my %new_metadata; for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); %new_metadata = ( %new_metadata, - %{ $metadata_for{$isa_class} || {} }, + %$isa_metadata, ); } - $metadata_for{$class} = \%new_metadata; + %$class_metadata = %new_metadata; } sub unimport { my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); } sub Dumper { @@ -3213,11 +3347,21 @@ BEGIN { } } +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + } 1; } # ########################################################################### -# End Mo package +# End Lmo package # ########################################################################### # ########################################################################### @@ -3382,7 +3526,7 @@ use warnings FATAL => 'all'; use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; -use Mo; +use Lmo; use Data::Dumper; sub get_cluster_name { @@ -3580,7 +3724,7 @@ sub deserialize_list { { package VersionParser; -use Mo; +use Lmo; use Scalar::Util qw(blessed); use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -3756,7 +3900,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } -no Mo; +no Lmo; 1; } # ########################################################################### @@ -3984,7 +4128,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); @@ -7211,24 +7355,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -7360,6 +7506,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -8771,12 +8920,13 @@ sub main { } if ( $master_binlog ne $slave_binlog ) { - $err .= $master_cxn->name() . " has binlog_format " - . $master_binlog . " but replica " . $slave_cxn->name() - . " has binlog_format $slave_binlog. This could cause " - . "pt-table-checksum to break replication. " - . "If you understand the risks, specify " - . "--no-check-binlog-format to disable this check.\n"; + $err .= "Replica " . $slave_cxn->name() + . qq{ has binlog_format $slave_binlog which could cause } + . qq{pt-table-checksum to break replication. Please read } + . qq{"Replicas using row-based replication" in the } + . qq{LIMITATIONS section of the tool's documentation. } + . qq{If you understand the risks, specify } + . qq{--no-check-binlog-format to disable this check.\n}; } } die $err if $err; @@ -11951,8 +12101,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -11970,6 +12120,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-table-checksum 2.1.7 +pt-table-checksum 2.1.8 =cut diff --git a/bin/pt-table-sync b/bin/pt-table-sync index b2957ac3..6f6abf9f 100755 --- a/bin/pt-table-sync +++ b/bin/pt-table-sync @@ -15,7 +15,11 @@ BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit OptionParser - Mo + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo Quoter DSNParser VersionParser @@ -36,7 +40,6 @@ BEGIN { SchemaIterator Transformers Retry - VersionCheck HTTPMicro Pingback )); @@ -52,7 +55,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -1086,18 +1089,24 @@ if ( PTDEBUG ) { # ########################################################################### # ########################################################################### -# Mo package +# Lmo::Utils package # This package is a copy without comments from the original. The original # with comments and its test file can be found in the Bazaar repository at, -# lib/Mo.pm -# t/lib/Mo.t +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t # See https://launchpad.net/percona-toolkit for more information. # ########################################################################### { +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} { no strict 'refs'; @@ -1110,6 +1119,172 @@ our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. } } +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +my %metadata_for; + +sub new { + shift; + return Lmo::Meta::Class->new(@_); +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + use strict; use warnings qw( FATAL all ); @@ -1131,240 +1306,276 @@ our %TYPES = ( } qw(Array Code Hash Regexp Glob Scalar) ); -our %metadata_for; -{ - package Mo::Object; +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; } - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; } - else { - $ref = { @_ }; - } - return $ref; + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); } } +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + my %export_for; -sub Mo::import { - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); +sub import { + warnings->import(qw(FATAL all)); + strict->import(); - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); + my $caller = scalar caller(); # Caller's package + my $caller_pkg = $caller . "::"; # Caller's package with :: at the end + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; } - } - return if $exports{M}; + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; + goto &$original_method + }; + } - $metadata_for{$caller}{$attribute} = (); - - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) } - }, - %exports, - ); + goto &$original_method; + } + } - $export_for{$caller} = [ keys %exports ]; + _install_coderef "${caller}::$attribute" => $method; - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } } sub _has_handles { @@ -1386,8 +1597,8 @@ sub _has_handles { $kv = { map { $_, $_ } grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } keys %{ _stash_for $target_class } }; } @@ -1413,80 +1624,32 @@ sub _has_handles { } } -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $inner_types = _nested_constraints($1, $2); - } - else { - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - return 1 if ! defined($value); - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - sub _set_package_isa { my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; } sub _set_inherited_metadata { my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); my $linearized_isa = mro::get_linear_isa($class); my %new_metadata; for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); %new_metadata = ( %new_metadata, - %{ $metadata_for{$isa_class} || {} }, + %$isa_metadata, ); } - $metadata_for{$class} = \%new_metadata; + %$class_metadata = %new_metadata; } sub unimport { my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); } sub Dumper { @@ -1529,11 +1692,21 @@ BEGIN { } } +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + } 1; } # ########################################################################### -# End Mo package +# End Lmo package # ########################################################################### # ########################################################################### @@ -2050,7 +2223,7 @@ sub _d { { package VersionParser; -use Mo; +use Lmo; use Scalar::Util qw(blessed); use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -2226,7 +2399,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } -no Mo; +no Lmo; 1; } # ########################################################################### @@ -7887,24 +8060,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -8036,6 +8211,9 @@ sub parse_timestamp { . (defined $f ? '%09.6f' : '%02d'), $y + 2000, $m, $d, $h, $i, (defined $f ? $s + $f : $s); } + elsif ( $val =~ m/^$proper_ts$/ ) { + return $val; + } return $val; } @@ -8293,300 +8471,6 @@ sub _d { # End Retry package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -9276,7 +9160,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -9352,10 +9235,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -9366,13 +9248,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -9402,7 +9284,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -9585,6 +9467,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -10579,6 +10705,7 @@ sub sync_a_table { trim => $o->get('trim'), wait => $o->get('wait'), function => $o->get('function'), + trace => !$ENV{PT_TEST_NO_TRACE}, ); if ( sum(@status{@ChangeHandler::ACTIONS}) ) { @@ -11278,19 +11405,30 @@ sub diff_where { PTDEBUG && _d('Ascend params:', Dumper($asc)); } - my $lb_sql = $asc->{boundaries}->{'>='}; - foreach my $val ( $q->deserialize_list($diff->{lower_boundary}) ) { - my $quoted_val = $q->quote_val($val); - $lb_sql =~ s/\?/$quoted_val/; + my ($lb_sql, $ub_sql); + + if ( defined $diff->{lower_boundary} ) { + $lb_sql = $asc->{boundaries}->{'>='}; + foreach my $val ( $q->deserialize_list($diff->{lower_boundary}) ) { + my $quoted_val = $q->quote_val($val); + $lb_sql =~ s/\?/$quoted_val/; + } } - my $ub_sql = $asc->{boundaries}->{'<='}; - foreach my $val ( $q->deserialize_list($diff->{upper_boundary}) ) { - my $quoted_val = $q->quote_val($val); - $ub_sql =~ s/\?/$quoted_val/; + if ( defined $diff->{upper_boundary} ) { + $ub_sql = $asc->{boundaries}->{'<='}; + foreach my $val ( $q->deserialize_list($diff->{upper_boundary}) ) { + my $quoted_val = $q->quote_val($val); + $ub_sql =~ s/\?/$quoted_val/; + } } - return "$lb_sql AND $ub_sql"; + die "Invalid checksum diff: " . Dumper($diff) + unless $lb_sql || $ub_sql; + + return $lb_sql && $ub_sql ? "$lb_sql AND $ub_sql" + : $lb_sql ? $lb_sql + : $ub_sql; } } @@ -12614,8 +12752,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -12633,6 +12771,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-table-sync 2.1.7 +pt-table-sync 2.1.8 =cut diff --git a/bin/pt-table-usage b/bin/pt-table-usage index 69b8c891..3a9767a3 100755 --- a/bin/pt-table-usage +++ b/bin/pt-table-usage @@ -5345,7 +5345,7 @@ sub new { } my $self = { - instrument => 0, + instrument => PTDEBUG, continue_on_error => 0, %args, @@ -5372,9 +5372,7 @@ sub add { push @{$self->{procs}}, $process; push @{$self->{names}}, $name; - if ( my $n = $args{retry_on_error} ) { - $self->{retries}->{$name} = $n; - } + $self->{retries}->{$name} = $args{retry_on_error} || 100; if ( $self->{instrument} ) { $self->{instrumentation}->{$name} = { time => 0, calls => 0 }; } @@ -5443,7 +5441,11 @@ sub execute { my $msg = "Pipeline process " . ($procno + 1) . " ($name) caused an error: " . $EVAL_ERROR; - if ( defined $self->{retries}->{$name} ) { + if ( !$self->{continue_on_error} ) { + die $msg . "Terminating pipeline because --continue-on-error " + . "is false.\n"; + } + elsif ( defined $self->{retries}->{$name} ) { my $n = $self->{retries}->{$name}; if ( $n ) { warn $msg . "Will retry pipeline process $procno ($name) " @@ -5455,9 +5457,6 @@ sub execute { . "($name) caused too many errors.\n"; } } - elsif ( !$self->{continue_on_error} ) { - die $msg; - } else { warn $msg; } @@ -7365,8 +7364,7 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2012-2013 Percona Ireland Ltd. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -7384,6 +7382,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-table-usage 2.1.7 +pt-table-usage 2.1.8 =cut diff --git a/bin/pt-upgrade b/bin/pt-upgrade index df972ecd..1b2c02fc 100755 --- a/bin/pt-upgrade +++ b/bin/pt-upgrade @@ -14,17 +14,20 @@ use warnings FATAL => 'all'; BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo DSNParser - OptionParser Quoter + OptionParser Transformers SlowLogParser - EventAggregator Daemon Outfile - VersionCheck + Retry HTTPMicro - Pingback )); } @@ -38,7 +41,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -46,6 +49,650 @@ our $VERSION = '2.1.7'; # End Percona::Toolkit package # ########################################################################### +# ########################################################################### +# Lmo::Utils package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + +BEGIN { + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} + +{ + no strict 'refs'; + sub _glob_for { + return \*{shift()} + } + + sub _stash_for { + return \%{ shift() . "::" }; + } +} + +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + + +our %TYPES = ( + Bool => sub { !$_[0] || (defined $_[0] && looks_like_number($_[0]) && $_[0] == 1) }, + Num => sub { defined $_[0] && looks_like_number($_[0]) }, + Int => sub { defined $_[0] && looks_like_number($_[0]) && $_[0] == int($_[0]) }, + Str => sub { defined $_[0] }, + Object => sub { defined $_[0] && blessed($_[0]) }, + FileHandle => sub { local $@; require IO::Handle; fileno($_[0]) && $_[0]->opened }, + + map { + my $type = /R/ ? $_ : uc $_; + $_ . "Ref" => sub { ref $_[0] eq $type } + } qw(Array Code Hash Regexp Glob Scalar) +); + +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} + +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; + + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; + } + + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; + } + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); + } +} + +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + +my %export_for; +sub import { + warnings->import(qw(FATAL all)); + strict->import(); + + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; + } + + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } + + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } + } + goto &$original_method + }; + } + + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) + } + goto &$original_method; + } + } + + _install_coderef "${caller}::$attribute" => $method; + + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } + + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } +} + +sub _has_handles { + my ($caller, $attribute, $args) = @_; + my $handles = $args->{handles}; + + my $ref = ref $handles; + my $kv; + if ( $ref eq ref [] ) { + $kv = { map { $_,$_ } @{$handles} }; + } + elsif ( $ref eq ref {} ) { + $kv = $handles; + } + elsif ( $ref eq ref qr// ) { + Carp::confess("Cannot delegate methods based on a Regexp without a type constraint (isa)") + unless $args->{isa}; + my $target_class = $args->{isa}; + $kv = { + map { $_, $_ } + grep { $_ =~ $handles } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } + keys %{ _stash_for $target_class } + }; + } + else { + Carp::confess("handles for $ref not yet implemented"); + } + + while ( my ($method, $target) = each %{$kv} ) { + my $name = _glob_for "${caller}::$method"; + Carp::confess("You cannot overwrite a locally defined method ($method) with a delegation") + if defined &$name; + + my ($target, @curried_args) = ref($target) ? @$target : $target; + *$name = sub { + my $self = shift; + my $delegate_to = $self->$attribute(); + my $error = "Cannot delegate $method to $target because the value of $attribute"; + Carp::confess("$error is not defined") unless $delegate_to; + Carp::confess("$error is not an object (got '$delegate_to')") + unless Scalar::Util::blessed($delegate_to) || (!ref($delegate_to) && $delegate_to->can($target)); + return $delegate_to->$target(@curried_args, @_); + } + } +} + +sub _set_package_isa { + my ($package, @new_isa) = @_; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; +} + +sub _set_inherited_metadata { + my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); + my $linearized_isa = mro::get_linear_isa($class); + my %new_metadata; + + for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); + %new_metadata = ( + %new_metadata, + %$isa_metadata, + ); + } + %$class_metadata = %new_metadata; +} + +sub unimport { + my $caller = scalar caller(); + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); +} + +sub Dumper { + require Data::Dumper; + local $Data::Dumper::Indent = 0; + local $Data::Dumper::Sortkeys = 0; + local $Data::Dumper::Quotekeys = 0; + local $Data::Dumper::Terse = 1; + + Data::Dumper::Dumper(@_) +} + +BEGIN { + if ($] >= 5.010) { + { local $@; require mro; } + } + else { + local $@; + eval { + require MRO::Compat; + } or do { + *mro::get_linear_isa = *mro::get_linear_isa_dfs = sub { + no strict 'refs'; + + my $classname = shift; + + my @lin = ($classname); + my %stored; + foreach my $parent (@{"$classname\::ISA"}) { + my $plin = mro::get_linear_isa_dfs($parent); + foreach (@$plin) { + next if exists $stored{$_}; + push(@lin, $_); + $stored{$_} = 1; + } + } + return \@lin; + }; + } + } +} + +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + +} +1; +} +# ########################################################################### +# End Lmo package +# ########################################################################### + # ########################################################################### # DSNParser package # This package is a copy without comments from the original. The original @@ -423,6 +1070,132 @@ sub _d { # End DSNParser package # ########################################################################### +# ########################################################################### +# Quoter package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Quoter.pm +# t/lib/Quoter.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Quoter; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use constant PTDEBUG => $ENV{PTDEBUG} || 0; + +sub new { + my ( $class, %args ) = @_; + return bless {}, $class; +} + +sub quote { + my ( $self, @vals ) = @_; + foreach my $val ( @vals ) { + $val =~ s/`/``/g; + } + return join('.', map { '`' . $_ . '`' } @vals); +} + +sub quote_val { + my ( $self, $val, %args ) = @_; + + return 'NULL' unless defined $val; # undef = NULL + return "''" if $val eq ''; # blank string = '' + return $val if $val =~ m/^0x[0-9a-fA-F]+$/ # quote hex data + && !$args{is_char}; # unless is_char is true + + $val =~ s/(['\\])/\\$1/g; + return "'$val'"; +} + +sub split_unquote { + my ( $self, $db_tbl, $default_db ) = @_; + my ( $db, $tbl ) = split(/[.]/, $db_tbl); + if ( !$tbl ) { + $tbl = $db; + $db = $default_db; + } + for ($db, $tbl) { + next unless $_; + s/\A`//; + s/`\z//; + s/``/`/g; + } + + return ($db, $tbl); +} + +sub literal_like { + my ( $self, $like ) = @_; + return unless $like; + $like =~ s/([%_])/\\$1/g; + return "'$like'"; +} + +sub join_quote { + my ( $self, $default_db, $db_tbl ) = @_; + return unless $db_tbl; + my ($db, $tbl) = split(/[.]/, $db_tbl); + if ( !$tbl ) { + $tbl = $db; + $db = $default_db; + } + $db = "`$db`" if $db && $db !~ m/^`/; + $tbl = "`$tbl`" if $tbl && $tbl !~ m/^`/; + return $db ? "$db.$tbl" : $tbl; +} + +sub serialize_list { + my ( $self, @args ) = @_; + return unless @args; + + return $args[0] if @args == 1 && !defined $args[0]; + + die "Cannot serialize multiple values with undef/NULL" + if grep { !defined $_ } @args; + + return join ',', map { quotemeta } @args; +} + +sub deserialize_list { + my ( $self, $string ) = @_; + return $string unless defined $string; + my @escaped_parts = $string =~ / + \G # Start of string, or end of previous match. + ( # Each of these is an element in the original list. + [^\\,]* # Anything not a backslash or a comma + (?: # When we get here, we found one of the above. + \\. # A backslash followed by something so we can continue + [^\\,]* # Same as above. + )* # Repeat zero of more times. + ) + , # Comma dividing elements + /sxgc; + + push @escaped_parts, pos($string) ? substr( $string, pos($string) ) : $string; + + my @unescaped_parts = map { + my $part = $_; + + my $char_class = utf8::is_utf8($part) # If it's a UTF-8 string, + ? qr/(?=\p{ASCII})\W/ # We only care about non-word + : qr/(?=\p{ASCII})\W|[\x{80}-\x{FF}]/; # Otherwise, + $part =~ s/\\($char_class)/$1/g; + $part; + } @escaped_parts; + + return @unescaped_parts; +} + +1; +} +# ########################################################################### +# End Quoter package +# ########################################################################### + # ########################################################################### # OptionParser package # This package is a copy without comments from the original. The original @@ -1448,132 +2221,6 @@ if ( PTDEBUG ) { # End OptionParser package # ########################################################################### -# ########################################################################### -# Quoter package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/Quoter.pm -# t/lib/Quoter.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package Quoter; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -sub new { - my ( $class, %args ) = @_; - return bless {}, $class; -} - -sub quote { - my ( $self, @vals ) = @_; - foreach my $val ( @vals ) { - $val =~ s/`/``/g; - } - return join('.', map { '`' . $_ . '`' } @vals); -} - -sub quote_val { - my ( $self, $val, %args ) = @_; - - return 'NULL' unless defined $val; # undef = NULL - return "''" if $val eq ''; # blank string = '' - return $val if $val =~ m/^0x[0-9a-fA-F]+$/ # quote hex data - && !$args{is_char}; # unless is_char is true - - $val =~ s/(['\\])/\\$1/g; - return "'$val'"; -} - -sub split_unquote { - my ( $self, $db_tbl, $default_db ) = @_; - my ( $db, $tbl ) = split(/[.]/, $db_tbl); - if ( !$tbl ) { - $tbl = $db; - $db = $default_db; - } - for ($db, $tbl) { - next unless $_; - s/\A`//; - s/`\z//; - s/``/`/g; - } - - return ($db, $tbl); -} - -sub literal_like { - my ( $self, $like ) = @_; - return unless $like; - $like =~ s/([%_])/\\$1/g; - return "'$like'"; -} - -sub join_quote { - my ( $self, $default_db, $db_tbl ) = @_; - return unless $db_tbl; - my ($db, $tbl) = split(/[.]/, $db_tbl); - if ( !$tbl ) { - $tbl = $db; - $db = $default_db; - } - $db = "`$db`" if $db && $db !~ m/^`/; - $tbl = "`$tbl`" if $tbl && $tbl !~ m/^`/; - return $db ? "$db.$tbl" : $tbl; -} - -sub serialize_list { - my ( $self, @args ) = @_; - return unless @args; - - return $args[0] if @args == 1 && !defined $args[0]; - - die "Cannot serialize multiple values with undef/NULL" - if grep { !defined $_ } @args; - - return join ',', map { quotemeta } @args; -} - -sub deserialize_list { - my ( $self, $string ) = @_; - return $string unless defined $string; - my @escaped_parts = $string =~ / - \G # Start of string, or end of previous match. - ( # Each of these is an element in the original list. - [^\\,]* # Anything not a backslash or a comma - (?: # When we get here, we found one of the above. - \\. # A backslash followed by something so we can continue - [^\\,]* # Same as above. - )* # Repeat zero of more times. - ) - , # Comma dividing elements - /sxgc; - - push @escaped_parts, pos($string) ? substr( $string, pos($string) ) : $string; - - my @unescaped_parts = map { - my $part = $_; - - my $char_class = utf8::is_utf8($part) # If it's a UTF-8 string, - ? qr/(?=\p{ASCII})\W/ # We only care about non-word - : qr/(?=\p{ASCII})\W|[\x{80}-\x{FF}]/; # Otherwise, - $part =~ s/\\($char_class)/$1/g; - $part; - } @escaped_parts; - - return @unescaped_parts; -} - -1; -} -# ########################################################################### -# End Quoter package -# ########################################################################### - # ########################################################################### # Transformers package # This package is a copy without comments from the original. The original @@ -1594,24 +2241,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; @@ -2393,283 +3042,67 @@ sub _d { # ########################################################################### # ########################################################################### -# VersionCheck package +# Retry package # This package is a copy without comments from the original. The original # with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t +# lib/Retry.pm +# t/lib/Retry.t # See https://launchpad.net/percona-toolkit for more information. # ########################################################################### { -package VersionCheck; +package Retry; use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); - use constant PTDEBUG => $ENV{PTDEBUG} || 0; -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - sub new { - my ($class, %args) = @_; + my ( $class, %args ) = @_; my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, + %args, }; return bless $self, $class; } -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); +sub retry { + my ( $self, %args ) = @_; + my @required_args = qw(try fail final_fail); foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); + die "I need a $arg argument" unless $args{$arg}; + }; + my ($try, $fail, $final_fail) = @args{@required_args}; + my $wait = $args{wait} || sub { sleep 1; }; + my $tries = $args{tries} || 3; + my $last_error; + my $tryno = 0; + TRY: + while ( ++$tryno <= $tries ) { + PTDEBUG && _d("Try", $tryno, "of", $tries); + my $result; eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } + $result = $try->(tryno=>$tryno); }; if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } + PTDEBUG && _d("Try code failed:", $EVAL_ERROR); + $last_error = $EVAL_ERROR; - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; + if ( $tryno < $tries ) { # more retries + my $retry = $fail->(tryno=>$tryno, error=>$last_error); + last TRY unless $retry; + PTDEBUG && _d("Calling wait code"); + $wait->(tryno=>$tryno); } } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } + else { + PTDEBUG && _d("Try code succeeded"); + return $result; } } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; + PTDEBUG && _d('Try code did not succeed'); + return $final_fail->(error=>$last_error); } sub _d { @@ -2683,7 +3116,7 @@ sub _d { 1; } # ########################################################################### -# End VersionCheck package +# End Retry package # ########################################################################### # ########################################################################### @@ -3335,369 +3768,6 @@ if ( $INC{"IO/Socket/SSL.pm"} ) { # End HTTPMicro package # ########################################################################### -# ########################################################################### -# Pingback package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/Pingback.pm -# t/lib/Pingback.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package Pingback; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use Data::Dumper qw(); -use Digest::MD5 qw(md5_hex); -use Sys::Hostname qw(hostname); -use Fcntl qw(:DEFAULT); -use File::Basename qw(); -use File::Spec; - -my $dir = File::Spec->tmpdir(); -my $check_time_file = File::Spec->catfile($dir,'percona-toolkit-version-check'); -my $check_time_limit = 60 * 60 * 24; # one day - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -local $EVAL_ERROR; -eval { - require Percona::Toolkit; - require HTTPMicro; - require VersionCheck; -}; - -sub version_check { - my %args = @_; - my @instances = $args{instances} ? @{ $args{instances} } : (); - - if (exists $ENV{PERCONA_VERSION_CHECK} && !$ENV{PERCONA_VERSION_CHECK}) { - warn '--version-check is disabled by the PERCONA_VERSION_CHECK ', - "environment variable.\n\n"; - return; - } - - $args{protocol} ||= 'https'; - my @protocols = $args{protocol} eq 'auto' - ? qw(https http) - : $args{protocol}; - - my $instances_to_check = []; - my $time = int(time()); - eval { - foreach my $instance ( @instances ) { - my ($name, $id) = _generate_identifier($instance); - $instance->{name} = $name; - $instance->{id} = $id; - } - - my $time_to_check; - ($time_to_check, $instances_to_check) - = time_to_check($check_time_file, \@instances, $time); - if ( !$time_to_check ) { - warn 'It is not time to --version-check again; ', - "only 1 check per day.\n\n"; - return; - } - - my $advice; - my $e; - for my $protocol ( @protocols ) { - $advice = eval { pingback( - url => $ENV{PERCONA_VERSION_CHECK_URL} || "$protocol://v.percona.com", - instances => $instances_to_check, - protocol => $protocol, - ) }; - last if !$advice && !$EVAL_ERROR; - $e ||= $EVAL_ERROR; - } - if ( $advice ) { - print "# Percona suggests these upgrades:\n"; - print join("\n", map { "# * $_" } @$advice), "\n\n"; - } - else { - die $e if $e; - print "# No suggestions at this time.\n\n"; - ($ENV{PTVCDEBUG} || PTDEBUG ) - && _d('--version-check worked, but there were no suggestions'); - } - }; - if ( $EVAL_ERROR ) { - warn "Error doing --version-check: $EVAL_ERROR"; - } - else { - update_checks_file($check_time_file, $instances_to_check, $time); - } - - return; -} - -sub pingback { - my (%args) = @_; - my @required_args = qw(url); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($url) = @args{@required_args}; - - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; - - $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); - - my $response = $ua->request('GET', $url); - ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); - die "No response from GET $url" - if !$response; - die("GET on $url returned HTTP status $response->{status}; expected 200\n", - ($response->{content} || '')) if $response->{status} != 200; - die("GET on $url did not return any programs to check") - if !$response->{content}; - - my $items = $vc->parse_server_response( - response => $response->{content} - ); - die "Failed to parse server requested programs: $response->{content}" - if !scalar keys %$items; - - my $versions = $vc->get_versions( - items => $items, - instances => $instances, - ); - die "Failed to get any program versions; should have at least gotten Perl" - if !scalar keys %$versions; - - my $client_content = encode_client_response( - items => $items, - versions => $versions, - general_id => md5_hex( hostname() ), - ); - - my $client_response = { - headers => { "X-Percona-Toolkit-Tool" => File::Basename::basename($0) }, - content => $client_content, - }; - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Client response:', Dumper($client_response)); - } - - $response = $ua->request('POST', $url, $client_response); - PTDEBUG && _d('Server suggestions:', Dumper($response)); - die "No response from POST $url $client_response" - if !$response; - die "POST $url returned HTTP status $response->{status}; expected 200" - if $response->{status} != 200; - - return unless $response->{content}; - - $items = $vc->parse_server_response( - response => $response->{content}, - split_vars => 0, - ); - die "Failed to parse server suggestions: $response->{content}" - if !scalar keys %$items; - my @suggestions = map { $_->{vars} } - sort { $a->{item} cmp $b->{item} } - values %$items; - - return \@suggestions; -} - -sub time_to_check { - my ($file, $instances, $time) = @_; - die "I need a file argument" unless $file; - $time ||= int(time()); # current time - - if ( @$instances ) { - my $instances_to_check = instances_to_check($file, $instances, $time); - return scalar @$instances_to_check, $instances_to_check; - } - - return 1 if !-f $file; - - my $mtime = (stat $file)[9]; - if ( !defined $mtime ) { - PTDEBUG && _d('Error getting modified time of', $file); - return 1; - } - PTDEBUG && _d('time=', $time, 'mtime=', $mtime); - if ( ($time - $mtime) > $check_time_limit ) { - return 1; - } - - return 0; -} - -sub instances_to_check { - my ($file, $instances, $time, %args) = @_; - - my $file_contents = ''; - if (open my $fh, '<', $file) { - chomp($file_contents = do { local $/ = undef; <$fh> }); - close $fh; - } - my %cached_instances = $file_contents =~ /^([^,]+),(.+)$/mg; - - my @instances_to_check; - foreach my $instance ( @$instances ) { - my $mtime = $cached_instances{ $instance->{id} }; - if ( !$mtime || (($time - $mtime) > $check_time_limit) ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Time to check MySQL instance', $instance->{name}); - } - push @instances_to_check, $instance; - $cached_instances{ $instance->{id} } = $time; - } - } - - if ( $args{update_file} ) { - open my $fh, '>', $file or die "Cannot open $file for writing: $OS_ERROR"; - while ( my ($id, $time) = each %cached_instances ) { - print { $fh } "$id,$time\n"; - } - close $fh or die "Cannot close $file: $OS_ERROR"; - } - - return \@instances_to_check; -} - -sub update_checks_file { - my ($file, $instances, $time) = @_; - - if ( !-f $file ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Creating time limit file', $file); - } - _touch($file); - } - - if ( $instances && @$instances ) { - instances_to_check($file, $instances, $time, update_file => 1); - return; - } - - my $mtime = (stat $file)[9]; - if ( !defined $mtime ) { - _touch($file); - return; - } - PTDEBUG && _d('time=', $time, 'mtime=', $mtime); - if ( ($time - $mtime) > $check_time_limit ) { - _touch($file); - return; - } - - return; -} - -sub _touch { - my ($file) = @_; - sysopen my $fh, $file, O_WRONLY|O_CREAT - or die "Cannot create $file : $!"; - close $fh or die "Cannot close $file : $!"; - utime(undef, undef, $file); -} - -sub _generate_identifier { - my $instance = shift; - my $dbh = $instance->{dbh}; - my $dsn = $instance->{dsn}; - - my $sql = q{SELECT CONCAT(@@hostname, @@port)}; - PTDEBUG && _d($sql); - my ($name) = eval { $dbh->selectrow_array($sql) }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d($EVAL_ERROR); - $sql = q{SELECT @@hostname}; - PTDEBUG && _d($sql); - ($name) = eval { $dbh->selectrow_array($sql) }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d($EVAL_ERROR); - $name = ($dsn->{h} || 'localhost') . ($dsn->{P} || 3306); - } - else { - $sql = q{SHOW VARIABLES LIKE 'port'}; - PTDEBUG && _d($sql); - my (undef, $port) = eval { $dbh->selectrow_array($sql) }; - PTDEBUG && _d('port:', $port); - $name .= $port || ''; - } - } - my $id = md5_hex($name); - - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('MySQL instance', $name, 'is', $id); - } - - return $name, $id; -} - -sub encode_client_response { - my (%args) = @_; - my @required_args = qw(items versions general_id); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items, $versions, $general_id) = @args{@required_args}; - - my @lines; - foreach my $item ( sort keys %$items ) { - next unless exists $versions->{$item}; - if ( ref($versions->{$item}) eq 'HASH' ) { - my $mysql_versions = $versions->{$item}; - for my $id ( sort keys %$mysql_versions ) { - push @lines, join(';', $id, $item, $mysql_versions->{$id}); - } - } - else { - push @lines, join(';', $general_id, $item, $versions->{$item}); - } - } - - my $client_response = join("\n", @lines) . "\n"; - return $client_response; -} - -sub validate_options { - my ($o) = @_; - - return if !$o->got('version-check'); - - my $value = $o->get('version-check'); - my @values = split /, /, - $o->read_para_after(__FILE__, qr/MAGIC_version_check/); - chomp(@values); - - return if grep { $value eq $_ } @values; - $o->save_error("--version-check invalid value $value. Accepted values are " - . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End Pingback package -# ########################################################################### - # ########################################################################### # This is a combination of modules and programs in one -- a runnable module. # http://www.perl.com/pub/a/2006/07/13/lightning-articles.html?page=last @@ -3886,6 +3956,15 @@ sub save_host_results { sub compare_results_to_host { } +sub get_cxn { + my ( $dp, $o, $dsn ) = @_; + if ( $o->get('ask-pass') ) { + $dsn->{p} = OptionParser::prompt_noecho("Enter password: "); + } + my $dbh = $dp->get_dbh($dp->get_cxn_params($dsn), {AutoCommit => 1}); + return $dbh; +} + sub disable_query_cache { my ($host) = @_; die "I need a host argument" unless $host; diff --git a/bin/pt-variable-advisor b/bin/pt-variable-advisor index bf6ce2e2..9c20df94 100755 --- a/bin/pt-variable-advisor +++ b/bin/pt-variable-advisor @@ -15,7 +15,11 @@ BEGIN { $INC{$_} = __FILE__ for map { (my $pkg = "$_.pm") =~ s!::!/!g; $pkg } (qw( Percona::Toolkit OptionParser - Mo + Lmo::Utils + Lmo::Meta + Lmo::Object + Lmo::Types + Lmo DSNParser VersionParser Daemon @@ -24,7 +28,6 @@ BEGIN { Advisor AdvisorRules VariableAdvisorRules - VersionCheck HTTPMicro Pingback )); @@ -40,7 +43,7 @@ BEGIN { # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } @@ -1074,18 +1077,24 @@ if ( PTDEBUG ) { # ########################################################################### # ########################################################################### -# Mo package +# Lmo::Utils package # This package is a copy without comments from the original. The original # with comments and its test file can be found in the Bazaar repository at, -# lib/Mo.pm -# t/lib/Mo.t +# lib/Lmo/Utils.pm +# t/lib/Lmo/Utils.t # See https://launchpad.net/percona-toolkit for more information. # ########################################################################### { +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} { no strict 'refs'; @@ -1098,6 +1107,194 @@ our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. } } +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; +} +# ########################################################################### +# End Lmo::Utils package +# ########################################################################### + +# ########################################################################### +# Lmo::Meta package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Meta.pm +# t/lib/Lmo/Meta.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} +# ########################################################################### +# End Lmo::Meta package +# ########################################################################### + +# ########################################################################### +# Lmo::Object package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Object.pm +# t/lib/Lmo/Object.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + $sub->( $self, @args); + } + return $self; +} + +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; +} +# ########################################################################### +# End Lmo::Object package +# ########################################################################### + +# ########################################################################### +# Lmo::Types package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo/Types.pm +# t/lib/Lmo/Types.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +package Lmo::Types; + use strict; use warnings qw( FATAL all ); @@ -1119,240 +1316,277 @@ our %TYPES = ( } qw(Array Code Hash Regexp Glob Scalar) ); -our %metadata_for; -{ - package Mo::Object; +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $inner_types = _nested_constraints($1, $2); + } + else { + $inner_types = $TYPES{$type}; } - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + return 1 if ! defined($value); + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; } - else { - $ref = { @_ }; - } - return $ref; + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); } } +1; +} +# ########################################################################### +# End Lmo::Types package +# ########################################################################### + +# ########################################################################### +# Lmo package +# This package is a copy without comments from the original. The original +# with comments and its test file can be found in the Bazaar repository at, +# lib/Lmo.pm +# t/lib/Lmo.t +# See https://launchpad.net/percona-toolkit for more information. +# ########################################################################### +{ +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + my %export_for; -sub Mo::import { - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); +sub import { + warnings->import(qw(FATAL all)); + strict->import(); - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + $export_for{$caller} = \%exports; + + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; } - } - return if $exports{M}; + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; + goto &$original_method + }; + } - $metadata_for{$caller}{$attribute} = (); - - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) } - }, - %exports, - ); + goto &$original_method; + } + } - $export_for{$caller} = [ keys %exports ]; + _install_coderef "${caller}::$attribute" => $method; - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } } sub _has_handles { @@ -1374,8 +1608,8 @@ sub _has_handles { $kv = { map { $_, $_ } grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } keys %{ _stash_for $target_class } }; } @@ -1401,80 +1635,32 @@ sub _has_handles { } } -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $inner_types = _nested_constraints($1, $2); - } - else { - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - return 1 if ! defined($value); - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - sub _set_package_isa { my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + @{*$package_isa} = @new_isa; } sub _set_inherited_metadata { my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); my $linearized_isa = mro::get_linear_isa($class); my %new_metadata; for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); %new_metadata = ( %new_metadata, - %{ $metadata_for{$isa_class} || {} }, + %$isa_metadata, ); } - $metadata_for{$class} = \%new_metadata; + %$class_metadata = %new_metadata; } sub unimport { my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); } sub Dumper { @@ -1517,11 +1703,21 @@ BEGIN { } } +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + } 1; } # ########################################################################### -# End Mo package +# End Lmo package # ########################################################################### # ########################################################################### @@ -1912,7 +2108,7 @@ sub _d { { package VersionParser; -use Mo; +use Lmo; use Scalar::Util qw(blessed); use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -2088,7 +2284,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } -no Mo; +no Lmo; 1; } # ########################################################################### @@ -3437,300 +3633,6 @@ sub _d { # End VariableAdvisorRules package # ########################################################################### -# ########################################################################### -# VersionCheck package -# This package is a copy without comments from the original. The original -# with comments and its test file can be found in the Bazaar repository at, -# lib/VersionCheck.pm -# t/lib/VersionCheck.t -# See https://launchpad.net/percona-toolkit for more information. -# ########################################################################### -{ -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### - # ########################################################################### # HTTPMicro package # This package is a copy without comments from the original. The original @@ -4420,7 +4322,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -4496,10 +4397,9 @@ sub pingback { } my ($url) = @args{@required_args}; - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); my $response = $ua->request('GET', $url); ($ENV{PTVCDEBUG} || PTDEBUG) && _d('Server response:', Dumper($response)); @@ -4510,13 +4410,13 @@ sub pingback { die("GET on $url did not return any programs to check") if !$response->{content}; - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" if !scalar keys %$items; - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -4546,7 +4446,7 @@ sub pingback { return unless $response->{content}; - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -4729,6 +4629,250 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -5851,8 +5995,7 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2010-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2010-2013 Percona Ireland Ltd. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -5870,6 +6013,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-variable-advisor 2.1.7 +pt-variable-advisor 2.1.8 =cut diff --git a/bin/pt-visual-explain b/bin/pt-visual-explain index 55bd1a33..eb43aa38 100755 --- a/bin/pt-visual-explain +++ b/bin/pt-visual-explain @@ -3124,8 +3124,8 @@ L for more software developed by Percona. =head1 COPYRIGHT, LICENSE, AND WARRANTY -This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. -Feedback and improvements are welcome. +This program is copyright 2011-2013 Percona Ireland Ltd, +2007-2011 Baron Schwartz. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF @@ -3143,6 +3143,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-visual-explain 2.1.7 +pt-visual-explain 2.1.8 =cut diff --git a/config/deb/changelog b/config/deb/changelog index 0440710a..189c9e3e 100644 --- a/config/deb/changelog +++ b/config/deb/changelog @@ -1,3 +1,41 @@ +percona-toolkit (2.1.8) unstable; urgency=low + + * Beta support for MySQL 5.6 + * Beta support for Percona XtraDB Cluster + * pt-online-schema-change: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer + * pt-table-checksum: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer + * pt-upgrade: Added --[no]disable-query-cache + * Fixed bug 927955: Bad pod2rst transformation + * Fixed bug 898665: Bad online docs formatting for --[no]vars + * Fixed bug 1022622: pt-config-diff is case-sensitive + * Fixed bug 1007938: pt-config-diff doesn't handle end-of-line comments + * Fixed bug 917770: pt-config-diff Use of uninitialized value in substitution (s///) at line 1996 + * Fixed bug 1082104: pt-deadlock-logger doesn't handle usernames with dashes + * Fixed bug 886059: pt-heartbeat handles timezones inconsistently + * Fixed bug 1086259: pt-kill --log-dsn timestamp is wrong + * Fixed bug 1015590: pt-mysql-summary doesn't handle renamed variables in Percona Server 5.5 + * Fixed bug 1079341: pt-online-schema-change checks for foreign keys on MyISAM tables + * Fixed bug 823431: pt-query-advisor hangs on big queries + * Fixed bug 996069: pt-query-advisor RES.001 is incorrect + * Fixed bug 933465: pt-query-advisor false positive on RES.001 + * Fixed bug 937234: pt-query-advisor issues wrong RES.001 + * Fixed bug 1082599: pt-query-digest fails to parse timestamp with no query + * Fixed bug 1078838: pt-query-digest doesn't parse general log with "Connect user as user" + * Fixed bug 957442: pt-query-digest with custom --group-by throws error + * Fixed bug 887638: pt-query-digest prints negative byte offset + * Fixed bug 831525: pt-query-digest help output mangled + * Fixed bug 932614: pt-slave-restart CHANGE MASTER query causes error + * Fixed bug 1046440: pt-stalk purge_samples slows down checks + * Fixed bug 986847: pt-stalk does not report NFS iostat + * Fixed bug 1074179: pt-table-checksum doesn't ignore tables for --replicate-check-only + * Fixed bug 911385: pt-table-checksum v2 fails when --resume + --ignore-database is used + * Fixed bug 1041391: pt-table-checksum debug statement for "Chosen hash func" prints undef + * Fixed bug 1075638: pt-table-checksum Illegal division by zero at line 7950 + * Fixed bug 1052475: pt-table-checksum uninitialized value in numeric lt (<) at line 8611 + * Fixed bug 1078887: Tools let --set-vars clobber the required SQL mode + + -- Percona Toolkit Developers Fri, 21 Dec 2012 17:31:09 +0000 + percona-toolkit (2.1.7) unstable; urgency=low * Fixed bug 1080384: pt-table-checksum 2.1.6 crashes using PTDEBUG diff --git a/config/sphinx-build/conf.py b/config/sphinx-build/conf.py index 47902245..76a304e2 100644 --- a/config/sphinx-build/conf.py +++ b/config/sphinx-build/conf.py @@ -50,7 +50,7 @@ copyright = u'2011, Percona Inc' # The short X.Y version. version = '2.1' # The full version, including alpha/beta/rc tags. -release = '2.1.7' +release = '2.1.8' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/percona-toolkit.pod b/docs/percona-toolkit.pod index 961dd38d..0dbd6f03 100644 --- a/docs/percona-toolkit.pod +++ b/docs/percona-toolkit.pod @@ -17,7 +17,7 @@ no libraries are installed. Percona Toolkit is derived from Maatkit and Aspersa, two of the best-known toolkits for MySQL server administration. It is developed and supported by -Percona Inc. For more information and other free, open-source software +Percona. For more information and other free, open-source software developed by Percona, visit L. =head1 TOOLS @@ -485,13 +485,33 @@ see L<"ENVIRONMENT">. =head1 AUTHORS -Percona Toolkit is primarily developed by Baron Schwartz and Daniel Nichter, -both of whom are employed by Percona Inc. See each program's documentation -for details. +=over + +=item Baron Schwartz + +Baron created Maatkit, from which Percona Toolkit was forked. Many of +the tools and modules were originally written by Baron. + +=item Daniel Nichter + +Daniel began helping Baron with Maatkit and, later, Percona Toolkit in +June, 2008. He is the project's lead developer, employed by Percona. + +=item Brian Fraser + +Brian started with Percona in December, 2011. He works on Percona Toolkit +full-time, employed by Percona. + +=item Others + +Many people have contributed code over the years. See each tool's +"AUTHORS" section for details. + +=back =head1 COPYRIGHT, LICENSE, AND WARRANTY -Percona Toolkit is copyright 2011-2012 Percona Inc. and others. +Percona Toolkit is copyright 2011-2013 Percona Ireland Ltd and others. See each program's documentation for complete copyright notices. THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -510,6 +530,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -Percona Toolkit v2.1.7 released 2012-11-19 +Percona Toolkit v2.1.8 released 2012-12-21 =cut diff --git a/docs/release_notes.rst b/docs/release_notes.rst index 8a3d1a08..9785cd1b 100644 --- a/docs/release_notes.rst +++ b/docs/release_notes.rst @@ -1,6 +1,89 @@ Release Notes ************* +v2.1.8 released 2012-12-21 +========================== + +Percona Toolkit 2.1.8 has been released. This release includes 28 bug fixes, beta support for MySQL 5.6, and extensive support for Percona XtraDB Cluster (PXC). Users intending on running the tools on Percona XtraDB Cluster or MySQL 5.6 should upgrade. The following tools have been verified to work on PXC versions 5.5.28 and newer: + +* pt-table-chcecksum +* pt-online-schema-change +* pt-archive +* pt-mysql-summary +* pt-heartbeat +* pt-variable-advisor +* pt-config-diff +* pt-deadlock-logger + +However, there are limitations when running these tools on PXC; see the Percona XtraDB Cluster section in each tool's documentation for further details. All other tools, with the exception of pt-slave-find, pt-slave-delay and pt-slave-restart, should also work correctly, but in some cases they have not been modified to take advantage of PXC features, so they may behave differently in future releases. + +The bug fixes are widely assorted. The following highlights some of the more interesting and "hot" bugs: + +* Fixed bug 1082599: pt-query-digest fails to parse timestamp with no query + +Slow logs which include timestamps but no query--which can happen if using slow_query_log_timestamp_always in Percona Server--were misparsed, resulting in an erroneous report. Now such no-query events show up in reports as ``/* No query */``. + +* Fixed bug 1078838: pt-query-digest doesn't parse general log with "Connect user as user" + +The "as" was misparsed and the following word would end up reported as the database; pt-query-digest now handles this correctly. + +* Fixed bug 1015590: pt-mysql-summary doesn't handle renamed variables in Percona Server 5.5 + +Some renamed variables had caused the Percona Server section to work unreliably. + +* Fixed bug 1074179: pt-table-checksum doesn't ignore tables for --replicate-check-only + +When using --replicate-check-only, filter options like --databases and --tables were not applied. + +* Fixed bug 886059: pt-heartbeat handles timezones inconsistently + +Previously, pt-heartbeat respected the MySQL time zone, but this caused false readings (e.g. very high lag) with slaves running in different time zones. Now pt-heartbeat uses UTC regardless of the server or MySQL time zone. + +* Fixed bug 1079341: pt-online-schema-change checks for foreign keys on MyISAM tables + +Since MyISAM tables can't have foreign keys, and the tool uses the information_schema to find child tables, this could cause unnecessary load on the server. + +2.1.8 continues the trend of solid bug fix releases, and all 2.1 users are encouraged to upgrade. + +Percona Toolkit packages can be downloaded from http://www.percona.com/downloads/percona-toolkit/ or the Percona Software Repositories (http://www.percona.com/software/repositories/). + +Changelog +--------- + +* Beta support for MySQL 5.6 +* Beta support for Percona XtraDB Cluster +* pt-online-schema-change: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer +* pt-table-checksum: If ran on Percona XtraDB Cluster, requires PXC 5.5.28 or newer +* pt-upgrade: Added --[no]disable-query-cache +* Fixed bug 927955: Bad pod2rst transformation +* Fixed bug 898665: Bad online docs formatting for --[no]vars +* Fixed bug 1022622: pt-config-diff is case-sensitive +* Fixed bug 1007938: pt-config-diff doesn't handle end-of-line comments +* Fixed bug 917770: pt-config-diff Use of uninitialized value in substitution (s///) at line 1996 +* Fixed bug 1082104: pt-deadlock-logger doesn't handle usernames with dashes +* Fixed bug 886059: pt-heartbeat handles timezones inconsistently +* Fixed bug 1086259: pt-kill --log-dsn timestamp is wrong +* Fixed bug 1015590: pt-mysql-summary doesn't handle renamed variables in Percona Server 5.5 +* Fixed bug 1079341: pt-online-schema-change checks for foreign keys on MyISAM tables +* Fixed bug 823431: pt-query-advisor hangs on big queries +* Fixed bug 996069: pt-query-advisor RES.001 is incorrect +* Fixed bug 933465: pt-query-advisor false positive on RES.001 +* Fixed bug 937234: pt-query-advisor issues wrong RES.001 +* Fixed bug 1082599: pt-query-digest fails to parse timestamp with no query +* Fixed bug 1078838: pt-query-digest doesn't parse general log with "Connect user as user" +* Fixed bug 957442: pt-query-digest with custom --group-by throws error +* Fixed bug 887638: pt-query-digest prints negative byte offset +* Fixed bug 831525: pt-query-digest help output mangled +* Fixed bug 932614: pt-slave-restart CHANGE MASTER query causes error +* Fixed bug 1046440: pt-stalk purge_samples slows down checks +* Fixed bug 986847: pt-stalk does not report NFS iostat +* Fixed bug 1074179: pt-table-checksum doesn't ignore tables for --replicate-check-only +* Fixed bug 911385: pt-table-checksum v2 fails when --resume + --ignore-database is used +* Fixed bug 1041391: pt-table-checksum debug statement for "Chosen hash func" prints undef +* Fixed bug 1075638: pt-table-checksum Illegal division by zero at line 7950 +* Fixed bug 1052475: pt-table-checksum uninitialized value in numeric lt (<) at line 8611 +* Fixed bug 1078887: Tools let --set-vars clobber the required SQL mode + v2.1.7 released 2012-11-19 ========================== diff --git a/lib/Advisor.pm b/lib/Advisor.pm index e22cd9cf..77aa224a 100644 --- a/lib/Advisor.pm +++ b/lib/Advisor.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/AdvisorRules.pm b/lib/AdvisorRules.pm index f815914e..e8c5dd99 100644 --- a/lib/AdvisorRules.pm +++ b/lib/AdvisorRules.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/BinaryLogParser.pm b/lib/BinaryLogParser.pm index b6804893..0caa3fb4 100644 --- a/lib/BinaryLogParser.pm +++ b/lib/BinaryLogParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/ChangeHandler.pm b/lib/ChangeHandler.pm index 1507b6ed..c8ac3977 100644 --- a/lib/ChangeHandler.pm +++ b/lib/ChangeHandler.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/CleanupTask.pm b/lib/CleanupTask.pm index 5401360b..f3f9ddac 100644 --- a/lib/CleanupTask.pm +++ b/lib/CleanupTask.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/CompareQueryTimes.pm b/lib/CompareQueryTimes.pm index 71c091a5..3faa6cb7 100644 --- a/lib/CompareQueryTimes.pm +++ b/lib/CompareQueryTimes.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -298,7 +298,7 @@ sub _report_diff_big { return unless keys %{$self->{diffs}->{big}}; my $report = new ReportFormatter(); - $report->set_title('Big query time differences'); + $report->title('Big query time differences'); my $hostno = 0; $report->set_columns( $args{query_id_col}, @@ -347,7 +347,7 @@ sub _report_diff_in_bucket { return unless keys %{$self->{diffs}->{in_bucket}}; my $report = new ReportFormatter(); - $report->set_title('Significant query time differences'); + $report->title('Significant query time differences'); my $hostno = 0; $report->set_columns( $args{query_id_col}, diff --git a/lib/CompareResults.pm b/lib/CompareResults.pm index e623601f..f760a917 100644 --- a/lib/CompareResults.pm +++ b/lib/CompareResults.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -874,7 +874,7 @@ sub _report_diff_checksums { return unless keys %{$self->{diffs}->{checksums}}; my $report = new ReportFormatter(); - $report->set_title('Checksum differences'); + $report->title('Checksum differences'); $report->set_columns( $args{query_id_col}, @{$args{host_cols}}, @@ -905,7 +905,7 @@ sub _report_diff_col_vals { return unless keys %{$self->{diffs}->{col_vals}}; my $report = new ReportFormatter(); - $report->set_title('Column value differences'); + $report->title('Column value differences'); $report->set_columns( $args{query_id_col}, { @@ -940,7 +940,7 @@ sub _report_diff_row_counts { return unless keys %{$self->{diffs}->{row_counts}}; my $report = new ReportFormatter(); - $report->set_title('Row count differences'); + $report->title('Row count differences'); my $hostno = 0; $report->set_columns( $args{query_id_col}, diff --git a/lib/CompareWarnings.pm b/lib/CompareWarnings.pm index 7cd30142..9c79a4c6 100644 --- a/lib/CompareWarnings.pm +++ b/lib/CompareWarnings.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -324,7 +324,7 @@ sub _report_diff_warnings { return unless keys %{$self->{diffs}->{warnings}}; my $report = new ReportFormatter(extend_right => 1); - $report->set_title('New warnings'); + $report->title('New warnings'); $report->set_columns( $args{query_id_col}, { name => 'Host', }, @@ -358,7 +358,7 @@ sub _report_diff_levels { return unless keys %{$self->{diffs}->{levels}}; my $report = new ReportFormatter(extend_right => 1); - $report->set_title('Warning level differences'); + $report->title('Warning level differences'); my $hostno = 0; $report->set_columns( $args{query_id_col}, @@ -396,7 +396,7 @@ sub _report_diff_warning_counts { return unless keys %{$self->{diffs}->{warning_counts}}; my $report = new ReportFormatter(); - $report->set_title('Warning count differences'); + $report->title('Warning count differences'); my $hostno = 0; $report->set_columns( $args{query_id_col}, diff --git a/lib/CopyRowsInsertSelect.pm b/lib/CopyRowsInsertSelect.pm index b210d902..74a704f7 100644 --- a/lib/CopyRowsInsertSelect.pm +++ b/lib/CopyRowsInsertSelect.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Cxn.pm b/lib/Cxn.pm index df7f6ce4..864abb3f 100644 --- a/lib/Cxn.pm +++ b/lib/Cxn.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/DSNParser.pm b/lib/DSNParser.pm index b4816724..f48939ab 100644 --- a/lib/DSNParser.pm +++ b/lib/DSNParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Daemon.pm b/lib/Daemon.pm index 75acaf78..2e53cccd 100644 --- a/lib/Daemon.pm +++ b/lib/Daemon.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2011 Percona Inc. +# This program is copyright 2008-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Diskstats.pm b/lib/Diskstats.pm index f12499a3..0365b8fd 100644 --- a/lib/Diskstats.pm +++ b/lib/Diskstats.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/DiskstatsGroupByAll.pm b/lib/DiskstatsGroupByAll.pm index 8627496d..75e8c417 100644 --- a/lib/DiskstatsGroupByAll.pm +++ b/lib/DiskstatsGroupByAll.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/DiskstatsGroupByDisk.pm b/lib/DiskstatsGroupByDisk.pm index 94fbefc6..e877e4c2 100644 --- a/lib/DiskstatsGroupByDisk.pm +++ b/lib/DiskstatsGroupByDisk.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/DiskstatsGroupBySample.pm b/lib/DiskstatsGroupBySample.pm index c8761a6e..3c4eca61 100644 --- a/lib/DiskstatsGroupBySample.pm +++ b/lib/DiskstatsGroupBySample.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/DiskstatsMenu.pm b/lib/DiskstatsMenu.pm index 86516001..0b054eba 100644 --- a/lib/DiskstatsMenu.pm +++ b/lib/DiskstatsMenu.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/DuplicateKeyFinder.pm b/lib/DuplicateKeyFinder.pm index b36b72a2..bef971ca 100644 --- a/lib/DuplicateKeyFinder.pm +++ b/lib/DuplicateKeyFinder.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/EventAggregator.pm b/lib/EventAggregator.pm index c1353016..9c922b15 100644 --- a/lib/EventAggregator.pm +++ b/lib/EventAggregator.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2011 Percona Inc. +# This program is copyright 2008-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -619,16 +619,6 @@ sub calculate_statistical_metrics { $classes->{$class}->{$attrib}->{all}, $classes->{$class}->{$attrib} ); - - # Apdex (http://code.google.com/p/maatkit/issues/detail?id=1054) - if ( $args{apdex_t} && $attrib eq 'Query_time' ) { - $class_metrics->{$class}->{$attrib}->{apdex_t} = $args{apdex_t}; - $class_metrics->{$class}->{$attrib}->{apdex} - = $self->calculate_apdex( - t => $args{apdex_t}, - samples => $classes->{$class}->{$attrib}->{all}, - ); - } } } } @@ -784,9 +774,6 @@ sub metrics { median => $metrics->{classes}->{$where}->{$attrib}->{median} || 0, pct_95 => $metrics->{classes}->{$where}->{$attrib}->{pct_95} || 0, stddev => $metrics->{classes}->{$where}->{$attrib}->{stddev} || 0, - - apdex_t => $metrics->{classes}->{$where}->{$attrib}->{apdex_t}, - apdex => $metrics->{classes}->{$where}->{$attrib}->{apdex}, }; } @@ -1164,70 +1151,6 @@ sub _deep_copy_attrib_vals { return $copy; } -# Sub: calculate_apdex -# Calculate the Apdex score for the given T and response times. -# -# -# Parameters: -# %args - Arguments -# -# Required Arguments: -# t - Target threshold -# samples - Hashref with bucketized response time values, -# i.e. { bucket_number => n_responses, } -# -# Returns: -# Apdex score -sub calculate_apdex { - my ( $self, %args ) = @_; - my @required_args = qw(t samples); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless $args{$arg}; - } - my ($t, $samples) = @args{@required_args}; - - if ( $t <= 0 ) { - die "Invalid target threshold (T): $t. T must be greater than zero"; - } - - my $f = 4 * $t; - PTDEBUG && _d("Apdex T =", $t, "F =", $f); - - my $satisfied = 0; - my $tolerating = 0; - my $frustrated = 0; # just for debug output - my $n_samples = 0; - BUCKET: - for my $bucket ( keys %$samples ) { - my $n_responses = $samples->{$bucket}; - my $response_time = $buck_vals[$bucket]; - - # Response time increases from 0 to F. - # 0 --- T --- F - # ^ ^-- tolerating zone - # | - # +-------- satisfied zone - if ( $response_time <= $t ) { - $satisfied += $n_responses; - } - elsif ( $response_time <= $f ) { - $tolerating += $n_responses; - } - else { - $frustrated += $n_responses; - } - - $n_samples += $n_responses; - } - - my $apdex = sprintf('%.2f', ($satisfied + ($tolerating / 2)) / $n_samples); - PTDEBUG && _d($n_samples, "samples,", $satisfied, "satisfied,", - $tolerating, "tolerating,", $frustrated, "frustrated, Apdex score:", - $apdex); - - return $apdex; -} - # Sub: _get_value # Get the value of the attribute (or one of its alternatives) from the event. # Undef is a valid value. If the attrib or none of its alternatives exist diff --git a/lib/EventTimeline.pm b/lib/EventTimeline.pm index d60ef8c8..8f8f6a9f 100644 --- a/lib/EventTimeline.pm +++ b/lib/EventTimeline.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2011 Percona Inc. +# This program is copyright 2008-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/ExecutionThrottler.pm b/lib/ExecutionThrottler.pm index d04aae1b..cf8b238b 100644 --- a/lib/ExecutionThrottler.pm +++ b/lib/ExecutionThrottler.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/ExplainAnalyzer.pm b/lib/ExplainAnalyzer.pm index cf04d0c6..b685ca9e 100644 --- a/lib/ExplainAnalyzer.pm +++ b/lib/ExplainAnalyzer.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -215,7 +215,7 @@ sub save_usage_for { # explain - Hashref of normalized EXPLAIN data # # Returns: -# Fingerprint/sparkline string +# Fingerprint string sub fingerprint { my ( $self, %args ) = @_; my @required_args = qw(explain); @@ -225,92 +225,6 @@ sub fingerprint { my ($explain) = @args{@required_args}; } -# Sub: sparkline -# Create a sparkline of EXPLAIN data from . A spark line -# is a very compact, terse fingerprint that represents just the following. -# See . -# -# access (for each table): -# - a: ALL -# - c: const -# - e: eq_ref -# - f: fulltext -# - i: index -# - m: index_merge -# - n: range -# - o: ref_or_null -# - r: ref -# - s: system -# - u: unique_subquery -# -# Extra: -# - uppsercaes access code: Using extra -# - T: Using temprary -# - F: Using filesort -# -# Parameters: -# %args - Arguments -# -# Required Arguments: -# explain - Hashref of normalized EXPLAIN data -# -# Returns: -# Sparkline string like (start code)TF>Ree(end code) -sub sparkline { - my ( $self, %args ) = @_; - my @required_args = qw(explain); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my ($explain) = @args{@required_args}; - PTDEBUG && _d("Making sparkline for", Dumper($explain)); - - my $access_code = { - 'ALL' => 'a', - 'const' => 'c', - 'eq_ref' => 'e', - 'fulltext' => 'f', - 'index' => 'i', - 'index_merge' => 'm', - 'range' => 'n', - 'ref_or_null' => 'o', - 'ref' => 'r', - 'system' => 's', - 'unique_subquery' => 'u', - }; - - my $sparkline = ''; - my ($T, $F); # Using temporary, Using filesort - - foreach my $tbl ( @$explain ) { - my $code; - if ( defined $tbl->{type} ) { - $code = $access_code->{$tbl->{type}} || "?"; - $code = uc $code if $tbl->{Extra}->{'Using index'}; - } - else { - $code = '-' - }; - $sparkline .= $code; - - $T = 1 if $tbl->{Extra}->{'Using temporary'}; - $F = 1 if $tbl->{Extra}->{'Using filesort'}; - } - - if ( $T || $F ) { - if ( $explain->[-1]->{Extra}->{'Using temporary'} - || $explain->[-1]->{Extra}->{'Using filesort'} ) { - $sparkline .= ">" . ($T ? "T" : "") . ($F ? "F" : ""); - } - else { - $sparkline = ($T ? "T" : "") . ($F ? "F" : "") . ">$sparkline"; - } - } - - PTDEBUG && _d("sparkline:", $sparkline); - return $sparkline; -} - sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } diff --git a/lib/FileIterator.pm b/lib/FileIterator.pm index 0552481f..c966453e 100644 --- a/lib/FileIterator.pm +++ b/lib/FileIterator.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/GeneralLogParser.pm b/lib/GeneralLogParser.pm index 14f47945..5c46f8c6 100644 --- a/lib/GeneralLogParser.pm +++ b/lib/GeneralLogParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/HTTPMicro.pm b/lib/HTTPMicro.pm index 90420d65..cc9d36cd 100644 --- a/lib/HTTPMicro.pm +++ b/lib/HTTPMicro.pm @@ -1,4 +1,4 @@ -# This program is copyright 2012 Percona Inc. +# This program is copyright 2012 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/HTTPProtocolParser.pm b/lib/HTTPProtocolParser.pm index 1974b1ce..aaa8e522 100644 --- a/lib/HTTPProtocolParser.pm +++ b/lib/HTTPProtocolParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/IndexLength.pm b/lib/IndexLength.pm index 15e65164..32bbfc58 100644 --- a/lib/IndexLength.pm +++ b/lib/IndexLength.pm @@ -1,4 +1,4 @@ -# This program is copyright 2012 Percona Inc. +# This program is copyright 2012 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/IndexUsage.pm b/lib/IndexUsage.pm index 06e169c8..d645f29a 100644 --- a/lib/IndexUsage.pm +++ b/lib/IndexUsage.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/JSONReportFormatter.pm b/lib/JSONReportFormatter.pm new file mode 100644 index 00000000..883b8069 --- /dev/null +++ b/lib/JSONReportFormatter.pm @@ -0,0 +1,125 @@ +{ +package JSONReportFormatter; +use Lmo; + +use List::Util qw(sum); +use Transformers qw(make_checksum parse_timestamp); + +use constant PTDEBUG => $ENV{PTDEBUG} || 0; + +my $have_json = eval { require JSON }; + +our $pretty_json = undef; +our $sorted_json = undef; + +extends qw(QueryReportFormatter); + +has _json => ( + is => 'ro', + init_arg => undef, + builder => '_build_json', +); + +sub _build_json { + return unless $have_json; + return JSON->new->utf8 + ->pretty($pretty_json) + ->canonical($sorted_json); +} + +sub encode_json { + my ($self, $encode) = @_; + if ( my $json = $self->_json ) { + return $json->encode($encode); + } + else { + return Transformers::encode_json($encode); + } +} + +override [qw(rusage date hostname files header profile prepared)] => sub { + return; +}; + +override event_report => sub { + my ($self, %args) = @_; + return $self->event_report_values(%args); +}; + +override query_report => sub { + my ($self, %args) = @_; + foreach my $arg ( qw(ea worst orderby groupby) ) { + die "I need a $arg argument" unless defined $arg; + } + + my $ea = $args{ea}; + my $worst = $args{worst}; + + my @attribs = @{$ea->get_attributes()}; + + my @queries; + foreach my $worst_info ( @$worst ) { + my $item = $worst_info->[0]; + my $stats = $ea->results->{classes}->{$item}; + my $sample = $ea->results->{samples}->{$item}; + + my $all_log_pos = $ea->{result_classes}->{$item}->{pos_in_log}->{all}; + my $times_seen = sum values %$all_log_pos; + + my %class = ( + sample => $sample->{arg}, + fingerprint => $item, + checksum => make_checksum($item), + cnt => $times_seen, + ); + + my %metrics; + foreach my $attrib ( @attribs ) { + $metrics{$attrib} = $ea->metrics( + attrib => $attrib, + where => $item, + ); + } + + foreach my $attrib ( keys %metrics ) { + if ( ! grep { $_ } values %{$metrics{$attrib}} ) { + delete $metrics{$attrib}; + next; + } + + if ($attrib eq 'ts') { + my $ts = delete $metrics{ts}; + foreach my $thing ( qw(min max) ) { + next unless defined $ts && defined $ts->{$thing}; + $ts->{$thing} = parse_timestamp($ts->{$thing}); + } + $class{ts_min} = $ts->{min}; + $class{ts_max} = $ts->{max}; + } + elsif ( ($ea->{type_for}->{$attrib} || '') eq 'num' ) { + # Avoid scientific notation in the metrics by forcing it to use + # six decimal places. + for my $value ( values %{$metrics{$attrib}} ) { + next unless $value; + $value = sprintf '%.6f', $value; + } + # ..except for the percentage, which only needs two + if ( my $pct = $metrics{$attrib}->{pct} ) { + $metrics{$attrib}->{pct} = sprintf('%.2f', $pct); + } + } + } + push @queries, { + class => \%class, + attributes => \%metrics, + }; + } + + my $json = $self->encode_json(\@queries); + $json .= "\n" if $json !~ /\n\Z/; + return $json . "\n"; +}; + +no Lmo; +1; +} diff --git a/lib/KeySize.pm b/lib/KeySize.pm index 8093cb11..6f52d8d6 100644 --- a/lib/KeySize.pm +++ b/lib/KeySize.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2011 Percona Inc. +# This program is copyright 2008-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Lmo.pm b/lib/Lmo.pm new file mode 100644 index 00000000..c6f688a0 --- /dev/null +++ b/lib/Lmo.pm @@ -0,0 +1,379 @@ +# This program is copyright 2007-2011 Baron Schwartz, 2012 Percona Ireland Ltd. +# Feedback and improvements are welcome. +# +# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar +# systems, you can issue `man perlgpl' or `man perlartistic' to read these +# licenses. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 59 Temple +# Place, Suite 330, Boston, MA 02111-1307 USA. +# ########################################################################### +# Lmo package +# ########################################################################### +# Package: Lmo +# Lmo provides a miniature object system in the style of Moose and Moo. +BEGIN { +$INC{"Lmo.pm"} = __FILE__; +package Lmo; +our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. + + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +use Lmo::Meta; +use Lmo::Object; +use Lmo::Types; + +use Lmo::Utils; + +my %export_for; +sub import { + # Set warnings and strict for the caller. + warnings->import(qw(FATAL all)); + strict->import(); + + my $caller = scalar caller(); # Caller's package + my %exports = ( + extends => \&extends, + has => \&has, + with => \&with, + override => \&override, + confess => \&Carp::confess, + ); + + # We keep this so code doing 'no Mo;' actually does a cleanup. + $export_for{$caller} = \%exports; + + # Export has, extends and sosuch. + for my $keyword ( keys %exports ) { + _install_coderef "${caller}::$keyword" => $exports{$keyword}; + } + + # Set up our caller's ISA, unless they already set it manually themselves, + # in which case we assume they know what they are doing. + # XXX weird syntax here because we want to call the classes' extends at + # least once, to avoid warnings. + if ( !@{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] } ) { + @_ = "Lmo::Object"; + goto *{ _glob_for "${caller}::extends" }{CODE}; + } +} + +sub extends { + my $caller = scalar caller(); + for my $class ( @_ ) { + _load_module($class); + } + _set_package_isa($caller, @_); + _set_inherited_metadata($caller); +} + +sub _load_module { + my ($class) = @_; + + # Try loading the class, but don't croak if we fail. + (my $file = $class) =~ s{::|'}{/}g; + $file .= '.pm'; + { local $@; eval { require "$file" } } # or warn $@; + return; +} + +sub with { + my $package = scalar caller(); + require Role::Tiny; + for my $role ( @_ ) { + _load_module($role); + _role_attribute_metadata($package, $role); + } + Role::Tiny->apply_roles_to_package($package, @_); +} + +sub _role_attribute_metadata { + my ($package, $role) = @_; + + my $package_meta = Lmo::Meta->metadata_for($package); + my $role_meta = Lmo::Meta->metadata_for($role); + + # The role metadata always comes first, since it shouldn't redefine + # metadata defined in the class itself. + %$package_meta = (%$role_meta, %$package_meta); +} + +sub has { + my $names = shift; + my $caller = scalar caller(); + + my $class_metadata = Lmo::Meta->metadata_for($caller); + + for my $attribute ( ref $names ? @$names : $names ) { + my %args = @_; + my $method = ($args{is} || '') eq 'ro' + ? sub { + Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller}::${attribute}") + if $#_; + return $_[0]{$attribute}; + } + : sub { + return $#_ + ? $_[0]{$attribute} = $_[1] + : $_[0]{$attribute}; + }; + + $class_metadata->{$attribute} = (); + + # isa => Constaint, + if ( my $type_check = $args{isa} ) { + my $check_name = $type_check; + + if ( my ($aggregate_type, $inner_type) = $type_check =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + $type_check = Lmo::Types::_nested_constraints($attribute, $aggregate_type, $inner_type); + } + + my $check_sub = sub { + my ($new_val) = @_; + Lmo::Types::check_type_constaints($attribute, $type_check, $check_name, $new_val); + }; + + $class_metadata->{$attribute}{isa} = [$check_name, $check_sub]; + my $orig_method = $method; + $method = sub { + $check_sub->($_[1]) if $#_; + goto &$orig_method; + }; + } + + # XXX TODO: Inline builder and default into the actual method, for speed. + # builder => '_builder_method', + if ( my $builder = $args{builder} ) { + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$builder + : goto &$original_method + }; + } + + # default => CodeRef, + if ( my $code = $args{default} ) { + Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") + unless ref($code) eq 'CODE'; + my $original_method = $method; + $method = sub { + $#_ + ? goto &$original_method + : ! exists $_[0]{$attribute} + ? $_[0]{$attribute} = $_[0]->$code + : goto &$original_method + }; + } + + # does => 'Role', + if ( my $role = $args{does} ) { + my $original_method = $method; + $method = sub { + if ( $#_ ) { + Carp::confess(qq) + unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } + } + goto &$original_method + }; + } + + # coerce => CodeRef, + if ( my $coercion = $args{coerce} ) { + $class_metadata->{$attribute}{coerce} = $coercion; + my $original_method = $method; + $method = sub { + if ( $#_ ) { + return $original_method->($_[0], $coercion->($_[1])) + } + goto &$original_method; + } + } + + # Actually put the attribute's accessor in the class + _install_coderef "${caller}::$attribute" => $method; + + if ( $args{required} ) { + $class_metadata->{$attribute}{required} = 1; + } + + if ($args{clearer}) { + _install_coderef "${caller}::$args{clearer}" + => sub { delete shift->{$attribute} } + } + + if ($args{predicate}) { + _install_coderef "${caller}::$args{predicate}" + => sub { exists shift->{$attribute} } + } + + if ($args{handles}) { + _has_handles($caller, $attribute, \%args); + } + + if (exists $args{init_arg}) { + $class_metadata->{$attribute}{init_arg} = $args{init_arg}; + } + } +} + +# handles handles +sub _has_handles { + my ($caller, $attribute, $args) = @_; + my $handles = $args->{handles}; + + my $ref = ref $handles; + my $kv; + if ( $ref eq ref [] ) { + # handles => [ ... list of methods ... ], + $kv = { map { $_,$_ } @{$handles} }; + } + elsif ( $ref eq ref {} ) { + # handles => { 'method_to_install' => 'original_method' | [ 'original_method', ... curried arguments ... ], }, + $kv = $handles; + } + elsif ( $ref eq ref qr// ) { + # handles => qr/PAT/, + Carp::confess("Cannot delegate methods based on a Regexp without a type constraint (isa)") + unless $args->{isa}; + my $target_class = $args->{isa}; + $kv = { + map { $_, $_ } + grep { $_ =~ $handles } + grep { !exists $Lmo::Object::{$_} && $target_class->can($_) } + grep { !$export_for{$target_class}->{$_} } + keys %{ _stash_for $target_class } + }; + } + else { + Carp::confess("handles for $ref not yet implemented"); + } + + while ( my ($method, $target) = each %{$kv} ) { + my $name = _glob_for "${caller}::$method"; + Carp::confess("You cannot overwrite a locally defined method ($method) with a delegation") + if defined &$name; + + # If we have an arrayref, they are currying some arguments. + my ($target, @curried_args) = ref($target) ? @$target : $target; + *$name = sub { + my $self = shift; + my $delegate_to = $self->$attribute(); + my $error = "Cannot delegate $method to $target because the value of $attribute"; + Carp::confess("$error is not defined") unless $delegate_to; + Carp::confess("$error is not an object (got '$delegate_to')") + unless Scalar::Util::blessed($delegate_to) || (!ref($delegate_to) && $delegate_to->can($target)); + return $delegate_to->$target(@curried_args, @_); + } + } +} + +# Sets a package's @ISA to the list passed in. Overwrites any previous values. +sub _set_package_isa { + my ($package, @new_isa) = @_; + my $package_isa = \*{ _glob_for "${package}::ISA" }; + # This somewhat weirder syntax is here to work around a Perl 5.10.0 bug; + # For whatever reason, some other variants weren't setting ISA. + @{*$package_isa} = @new_isa; +} + +# Each class has its own metadata. When a class inhyerits attributes, +# it should also inherit the attribute metadata. +sub _set_inherited_metadata { + my $class = shift; + my $class_metadata = Lmo::Meta->metadata_for($class); + my $linearized_isa = mro::get_linear_isa($class); + my %new_metadata; + + # Walk @ISA in reverse, grabbing the metadata for each + # class. Attributes with the same name defined in more + # specific classes override their parent's attributes. + for my $isa_class (reverse @$linearized_isa) { + my $isa_metadata = Lmo::Meta->metadata_for($isa_class); + %new_metadata = ( + %new_metadata, + %$isa_metadata, + ); + } + %$class_metadata = %new_metadata; +} + +sub unimport { + my $caller = scalar caller(); + my $target = caller; + _unimport_coderefs($target, keys %{$export_for{$caller}}); +} + +sub Dumper { + require Data::Dumper; + local $Data::Dumper::Indent = 0; + local $Data::Dumper::Sortkeys = 0; + local $Data::Dumper::Quotekeys = 0; + local $Data::Dumper::Terse = 1; + + Data::Dumper::Dumper(@_) +} + +BEGIN { + # mro is the method resolution order. The module itself is core in + # recent Perls; In older Perls it's available from MRO::Compat from + # CPAN, and in case that isn't available to us, we inline the barest + # funcionality. + if ($] >= 5.010) { + { local $@; require mro; } + } + else { + local $@; + eval { + require MRO::Compat; + } or do { + *mro::get_linear_isa = *mro::get_linear_isa_dfs = sub { + no strict 'refs'; + + my $classname = shift; + + my @lin = ($classname); + my %stored; + foreach my $parent (@{"$classname\::ISA"}) { + my $plin = mro::get_linear_isa_dfs($parent); + foreach (@$plin) { + next if exists $stored{$_}; + push(@lin, $_); + $stored{$_} = 1; + } + } + return \@lin; + }; + } + } +} + +sub override { + my ($methods, $code) = @_; + my $caller = scalar caller; + + for my $method ( ref($methods) ? @$methods : $methods ) { + my $full_method = "${caller}::${method}"; + *{_glob_for $full_method} = $code; + } +} + +} +1; +# ########################################################################### +# End Lmo package +# ########################################################################### diff --git a/lib/Lmo/Meta.pm b/lib/Lmo/Meta.pm new file mode 100644 index 00000000..ee2aeb75 --- /dev/null +++ b/lib/Lmo/Meta.pm @@ -0,0 +1,45 @@ +{ +package Lmo::Meta; +use strict; +use warnings qw( FATAL all ); + +my %metadata_for; + +sub new { + my $class = shift; + return bless { @_ }, $class +} + +sub metadata_for { + my $self = shift; + my ($class) = @_; + + return $metadata_for{$class} ||= {}; +} + +sub class { shift->{class} } + +sub attributes { + my $self = shift; + return keys %{$self->metadata_for($self->class)} +} + +sub attributes_for_new { + my $self = shift; + my @attributes; + + my $class_metadata = $self->metadata_for($self->class); + while ( my ($attr, $meta) = each %$class_metadata ) { + if ( exists $meta->{init_arg} ) { + push @attributes, $meta->{init_arg} + if defined $meta->{init_arg}; + } + else { + push @attributes, $attr; + } + } + return @attributes; +} + +1; +} \ No newline at end of file diff --git a/lib/Lmo/Object.pm b/lib/Lmo/Object.pm new file mode 100644 index 00000000..2f587172 --- /dev/null +++ b/lib/Lmo/Object.pm @@ -0,0 +1,97 @@ +# Mo::Object is the parent of every Mo-derived object. Here's where new +# and BUILDARGS gets inherited from. +package Lmo::Object; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(blessed); + +use Lmo::Meta; +use Lmo::Utils qw(_glob_for); + +sub new { + my $class = shift; + my $args = $class->BUILDARGS(@_); + + my $class_metadata = Lmo::Meta->metadata_for($class); + + my @args_to_delete; + while ( my ($attr, $meta) = each %$class_metadata ) { + next unless exists $meta->{init_arg}; + my $init_arg = $meta->{init_arg}; + + # If init_arg is defined, then we + if ( defined $init_arg ) { + $args->{$attr} = delete $args->{$init_arg}; + } + else { + push @args_to_delete, $attr; + } + } + + delete $args->{$_} for @args_to_delete; + + for my $attribute ( keys %$args ) { + # coerce + if ( my $coerce = $class_metadata->{$attribute}{coerce} ) { + $args->{$attribute} = $coerce->($args->{$attribute}); + } + # isa + if ( my $isa_check = $class_metadata->{$attribute}{isa} ) { + my ($check_name, $check_sub) = @$isa_check; + $check_sub->($args->{$attribute}); + } + } + + while ( my ($attribute, $meta) = each %$class_metadata ) { + next unless $meta->{required}; + Carp::confess("Attribute ($attribute) is required for $class") + if ! exists $args->{$attribute} + } + + my $self = bless $args, $class; + + # BUILD + my @build_subs; + my $linearized_isa = mro::get_linear_isa($class); + + for my $isa_class ( @$linearized_isa ) { + unshift @build_subs, *{ _glob_for "${isa_class}::BUILD" }{CODE}; + } + # If &class::BUILD exists, for every class in + # the linearized ISA, call it. + # XXX I _think_ that this uses exists correctly, since + # a class could define a stub for BUILD and then AUTOLOAD + # the body. Should check what Moose does. + my @args = %$args; + for my $sub (grep { defined($_) && exists &$_ } @build_subs) { + # @args must be defined outside of this loop, + # as changes to @_ in one BUILD should propagate to another + $sub->( $self, @args); + } + return $self; +} + +# Base BUILDARGS. +sub BUILDARGS { + shift; # No need for the classname + if ( @_ == 1 && ref($_[0]) ) { + Carp::confess("Single parameters to new() must be a HASH ref, not $_[0]") + unless ref($_[0]) eq ref({}); + return {%{$_[0]}} # We want a new reference, always + } + else { + return { @_ }; + } +} + +sub meta { + my $class = shift; + $class = Scalar::Util::blessed($class) || $class; + return Lmo::Meta->new(class => $class); +} + + +1; diff --git a/lib/Lmo/Role.pm b/lib/Lmo/Role.pm new file mode 100644 index 00000000..411f7da3 --- /dev/null +++ b/lib/Lmo/Role.pm @@ -0,0 +1,72 @@ +package Lmo::Role; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use constant PTDEBUG => $ENV{PTDEBUG} || 0; + +use Lmo (); +use base qw(Role::Tiny); + +use Lmo::Utils qw(_install_coderef _unimport_coderefs _stash_for); + +BEGIN { *INFO = \%Role::Tiny::INFO } + +our %INFO; + +sub _install_tracked { + my ($target, $name, $code) = @_; + $INFO{$target}{exports}{$name} = $code; + _install_coderef "${target}::${name}" => $code; +} + +sub import { + my $target = caller; + my ($me) = @_; + # Set warnings and strict for the caller. + warnings->import(qw(FATAL all)); + strict->import(); + +=begin + if ($Moo::MAKERS{$target} and $Moo::MAKERS{$target}{is_class}) { + die "Cannot import Moo::Role into a Moo class"; + } +=cut + return if $INFO{$target}; # already exported into this package + $INFO{$target} = { is_role => 1 }; + # get symbol table reference_unimport_coderefs + my $stash = _stash_for $target; + + _install_tracked $target => has => \*Lmo::has; + + # install before/after/around subs + foreach my $type (qw(before after around)) { + _install_tracked $target => $type => sub { + require Class::Method::Modifiers; + push @{$INFO{$target}{modifiers}||=[]}, [ $type => @_ ]; + }; + } + + _install_tracked $target => requires => sub { + push @{$INFO{$target}{requires}||=[]}, @_; + }; + + _install_tracked $target => with => \*Lmo::with; + + # grab all *non-constant* (stash slot is not a scalarref) subs present + # in the symbol table and store their refaddrs (no need to forcibly + # inflate constant subs into real subs) - also add '' to here (this + # is used later) with a map to the coderefs in case of copying or re-use + my @not_methods = ('', map { *$_{CODE}||() } grep !ref($_), values %$stash); + @{$INFO{$target}{not_methods}={}}{@not_methods} = @not_methods; + # a role does itself + $Role::Tiny::APPLIED_TO{$target} = { $target => undef }; + +} + +sub unimport { + my $target = caller; + _unimport_coderefs($target, keys %{$INFO{$target}{exports}}); +} + +1; diff --git a/lib/Lmo/Types.pm b/lib/Lmo/Types.pm new file mode 100644 index 00000000..12d8b540 --- /dev/null +++ b/lib/Lmo/Types.pm @@ -0,0 +1,98 @@ +package Lmo::Types; + +use strict; +use warnings qw( FATAL all ); + +use Carp (); +use Scalar::Util qw(looks_like_number blessed); + +# Basic types for isa. If you want a new type, either add it here, +# or give isa a coderef. + +our %TYPES = ( + Bool => sub { !$_[0] || (defined $_[0] && looks_like_number($_[0]) && $_[0] == 1) }, + Num => sub { defined $_[0] && looks_like_number($_[0]) }, + Int => sub { defined $_[0] && looks_like_number($_[0]) && $_[0] == int($_[0]) }, + Str => sub { defined $_[0] }, + Object => sub { defined $_[0] && blessed($_[0]) }, + FileHandle => sub { local $@; require IO::Handle; fileno($_[0]) && $_[0]->opened }, + + map { + my $type = /R/ ? $_ : uc $_; + $_ . "Ref" => sub { ref $_[0] eq $type } + } qw(Array Code Hash Regexp Glob Scalar) +); + +sub check_type_constaints { + my ($attribute, $type_check, $check_name, $val) = @_; + ( ref($type_check) eq 'CODE' + ? $type_check->($val) + : (ref $val eq $type_check + || ($val && $val eq $type_check) + || (exists $TYPES{$type_check} && $TYPES{$type_check}->($val))) + ) + || Carp::confess( + qq + . qq + . (defined $val ? Lmo::Dumper($val) : 'undef') ) +} + +# Nested (or parametized) constraints look like this: ArrayRef[CONSTRAINT] or +# Maybe[CONSTRAINT]. This function returns a coderef that implements one of +# these. +sub _nested_constraints { + my ($attribute, $aggregate_type, $type) = @_; + + my $inner_types; + if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { + # If the inner constraint -- the part within brackets -- is also a parametized + # constraint, then call this function recursively. + $inner_types = _nested_constraints($1, $2); + } + else { + # Otherwise, try checking if it's one of the built-in types. + $inner_types = $TYPES{$type}; + } + + if ( $aggregate_type eq 'ArrayRef' ) { + return sub { + my ($val) = @_; + return unless ref($val) eq ref([]); + + if ($inner_types) { + for my $value ( @{$val} ) { + return unless $inner_types->($value) + } + } + else { + # $inner_types isn't set, we are dealing with a class name. + for my $value ( @{$val} ) { + return unless $value && ($value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type))); + } + } + return 1; + }; + } + elsif ( $aggregate_type eq 'Maybe' ) { + return sub { + my ($value) = @_; + # For Maybe, undef is valid + return 1 if ! defined($value); + # Otherwise, defer to the inner type + if ($inner_types) { + return unless $inner_types->($value) + } + else { + return unless $value eq $type + || (Scalar::Util::blessed($value) && $value->isa($type)); + } + return 1; + } + } + else { + Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); + } +} + +1; diff --git a/lib/Lmo/Utils.pm b/lib/Lmo/Utils.pm new file mode 100644 index 00000000..4cd89565 --- /dev/null +++ b/lib/Lmo/Utils.pm @@ -0,0 +1,46 @@ +package Lmo::Utils; +use strict; +use warnings qw( FATAL all ); +require Exporter; +our (@ISA, @EXPORT, @EXPORT_OK); + +BEGIN { + @ISA = qw(Exporter); + @EXPORT = @EXPORT_OK = qw(_install_coderef _unimport_coderefs _glob_for _stash_for); +} + +{ + # Gets the glob from a given string. + no strict 'refs'; + sub _glob_for { + return \*{shift()} + } + + # Gets the stash from a given string. + # A stash is a symbol table hash; rough explanation on + # http://perldoc.perl.org/perlguts.html#Stashes-and-Globs + # But the gist of it is that we can use a hash-like thing to + # refer to a class and modify it. + sub _stash_for { + return \%{ shift() . "::" }; + } +} + +sub _install_coderef { + my ($to, $code) = @_; + + return *{ _glob_for $to } = $code; +} + +sub _unimport_coderefs { + my ($target, @names) = @_; + return unless @names; + my $stash = _stash_for($target); + foreach my $name (@names) { + if ($stash->{$name} and defined(&{$stash->{$name}})) { + delete $stash->{$name}; + } + } +} + +1; diff --git a/lib/MasterSlave.pm b/lib/MasterSlave.pm index a60f63c4..cf3c2aa9 100644 --- a/lib/MasterSlave.pm +++ b/lib/MasterSlave.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011-2012 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/MemcachedEvent.pm b/lib/MemcachedEvent.pm index e5d89dcb..ca2f637e 100644 --- a/lib/MemcachedEvent.pm +++ b/lib/MemcachedEvent.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/MemcachedProtocolParser.pm b/lib/MemcachedProtocolParser.pm index e2f573a6..2da3cf88 100644 --- a/lib/MemcachedProtocolParser.pm +++ b/lib/MemcachedProtocolParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Percona Inc. +# This program is copyright 2007-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Mo.pm b/lib/Mo.pm deleted file mode 100644 index ba96a512..00000000 --- a/lib/Mo.pm +++ /dev/null @@ -1,519 +0,0 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2012 Percona Inc. -# Feedback and improvements are welcome. -# -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar -# systems, you can issue `man perlgpl' or `man perlartistic' to read these -# licenses. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple -# Place, Suite 330, Boston, MA 02111-1307 USA. -# ########################################################################### -# Mo package -# ########################################################################### -# Package: Mo -# Mo provides a miniature object system in the style of Moose and Moo. -BEGIN { -$INC{"Mo.pm"} = __FILE__; -package Mo; -our $VERSION = '0.30_Percona'; # Forked from 0.30 of Mo. - -{ - # Gets the glob from a given string. - no strict 'refs'; - sub _glob_for { - return \*{shift()} - } - - # Gets the stash from a given string. A larger explanation about hashes in Mo::Percona - sub _stash_for { - return \%{ shift() . "::" }; - } -} - -use strict; -use warnings qw( FATAL all ); - -use Carp (); -use Scalar::Util qw(looks_like_number blessed); - -# Basic types for isa. If you want a new type, either add it here, -# or give isa a coderef. - -our %TYPES = ( - Bool => sub { !$_[0] || (defined $_[0] && looks_like_number($_[0]) && $_[0] == 1) }, - Num => sub { defined $_[0] && looks_like_number($_[0]) }, - Int => sub { defined $_[0] && looks_like_number($_[0]) && $_[0] == int($_[0]) }, - Str => sub { defined $_[0] }, - Object => sub { defined $_[0] && blessed($_[0]) }, - FileHandle => sub { local $@; require IO::Handle; fileno($_[0]) && $_[0]->opened }, - - map { - my $type = /R/ ? $_ : uc $_; - $_ . "Ref" => sub { ref $_[0] eq $type } - } qw(Array Code Hash Regexp Glob Scalar) -); - -our %metadata_for; -{ - # Mo::Object is the parent of every Mo-derived object. Here's where new - # and BUILDARGS gets inherited from. - package Mo::Object; - - sub new { - my $class = shift; - my $args = $class->BUILDARGS(@_); - - my @args_to_delete; - while ( my ($attr, $meta) = each %{$metadata_for{$class}} ) { - next unless exists $meta->{init_arg}; - my $init_arg = $meta->{init_arg}; - - # If init_arg is defined, then we - if ( defined $init_arg ) { - $args->{$attr} = delete $args->{$init_arg}; - } - else { - push @args_to_delete, $attr; - } - } - - delete $args->{$_} for @args_to_delete; - - for my $attribute ( keys %$args ) { - # coerce - if ( my $coerce = $metadata_for{$class}{$attribute}{coerce} ) { - $args->{$attribute} = $coerce->($args->{$attribute}); - } - # isa - if ( my $I = $metadata_for{$class}{$attribute}{isa} ) { - ( (my $I_name), $I ) = @{$I}; - Mo::_check_type_constaints($attribute, $I, $I_name, $args->{$attribute}); - } - } - - while ( my ($attribute, $meta) = each %{$metadata_for{$class}} ) { - next unless $meta->{required}; - Carp::confess("Attribute ($attribute) is required for $class") - if ! exists $args->{$attribute} - } - - @_ = %$args; - my $self = bless $args, $class; - - # BUILD - my @build_subs; - my $linearized_isa = mro::get_linear_isa($class); - - for my $isa_class ( @$linearized_isa ) { - unshift @build_subs, *{ Mo::_glob_for "${isa_class}::BUILD" }{CODE}; - } - # If &class::BUILD exists, for every class in - # the linearized ISA, call it. - # XXX I _think_ that this uses exists correctly, since - # a class could define a stub for BUILD and then AUTOLOAD - # the body. Should check what Moose does. - exists &$_ && $_->( $self, @_ ) for grep { defined } @build_subs; - return $self; - } - - # Base BUILDARGS. - sub BUILDARGS { - shift; - my $ref; - if ( @_ == 1 && ref($_[0]) ) { - Carp::confess("Single parameters to new() must be a HASH ref") - unless ref($_[0]) eq ref({}); - $ref = {%{$_[0]}} # We want a new reference, always - } - else { - $ref = { @_ }; - } - return $ref; - } -} - -my %export_for; -sub Mo::import { - # Set warnings and strict for the caller. - warnings->import(qw(FATAL all)); - strict->import(); - - my $caller = scalar caller(); # Caller's package - my $caller_pkg = $caller . "::"; # Caller's package with :: at the end - my (%exports, %options); - - # Load each feature and call its &e. - my (undef, @features) = @_; - my %ignore = ( map { $_ => 1 } qw( is isa init_arg builder buildargs clearer predicate build handles default required ) ); - for my $feature (grep { !$ignore{$_} } @features) { - { local $@; require "Mo/$feature.pm"; } - { - no strict 'refs'; - &{"Mo::${feature}::e"}( - $caller_pkg, - \%exports, - \%options, - \@_ - ); - } - } - - return if $exports{M}; - - %exports = ( - extends => sub { - for my $class ( map { "$_" } @_ ) { - # Try loading the class, but don't croak if we fail. - $class =~ s{::|'}{/}g; - { local $@; eval { require "$class.pm" } } # or warn $@; - } - _set_package_isa($caller, @_); - _set_inherited_metadata($caller); - }, - has => sub { - my $names = shift; - for my $attribute ( ref $names ? @$names : $names ) { - my %args = @_; - my $method = ($args{is} || '') eq 'ro' - ? sub { - Carp::confess("Cannot assign a value to a read-only accessor at reader ${caller_pkg}${attribute}") - if $#_; - return $_[0]{$attribute}; - } - : sub { - return $#_ - ? $_[0]{$attribute} = $_[1] - : $_[0]{$attribute}; - }; - - $metadata_for{$caller}{$attribute} = (); - - # isa => Constaint, - if ( my $I = $args{isa} ) { - my $orig_I = $I; - my $type; - if ( $I =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - $I = _nested_constraints($attribute, $1, $2); - } - $metadata_for{$caller}{$attribute}{isa} = [$orig_I, $I]; - my $orig_method = $method; - $method = sub { - if ( $#_ ) { - Mo::_check_type_constaints($attribute, $I, $orig_I, $_[1]); - } - goto &$orig_method; - }; - } - - # XXX TODO: Inline builder and default into the actual method, for speed. - # builder => '_builder_method', - if ( my $builder = $args{builder} ) { - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$builder - : goto &$original_method - }; - } - - # default => CodeRef, - if ( my $code = $args{default} ) { - Carp::confess("${caller}::${attribute}'s default is $code, but should be a coderef") - unless ref($code) eq 'CODE'; - my $original_method = $method; - $method = sub { - $#_ - ? goto &$original_method - : ! exists $_[0]{$attribute} - ? $_[0]{$attribute} = $_[0]->$code - : goto &$original_method - }; - } - - # does => 'Role', - if ( my $role = $args{does} ) { - my $original_method = $method; - $method = sub { - if ( $#_ ) { - Carp::confess(qq) - unless Scalar::Util::blessed($_[1]) && eval { $_[1]->does($role) } - } - goto &$original_method - }; - } - - # coerce => CodeRef, - if ( my $coercion = $args{coerce} ) { - $metadata_for{$caller}{$attribute}{coerce} = $coercion; - my $original_method = $method; - $method = sub { - if ( $#_ ) { - return $original_method->($_[0], $coercion->($_[1])) - } - goto &$original_method; - } - } - - # Call the extra features; that is, things loaded from - # the Mo::etc namespace, and not implemented here. - $method = $options{$_}->($method, $attribute, @_) - for sort keys %options; - - # Actually put the attribute's accessor in the class - *{ _glob_for "${caller}::$attribute" } = $method; - - if ( $args{required} ) { - $metadata_for{$caller}{$attribute}{required} = 1; - } - - if ($args{clearer}) { - *{ _glob_for "${caller}::$args{clearer}" } - = sub { delete shift->{$attribute} } - } - - if ($args{predicate}) { - *{ _glob_for "${caller}::$args{predicate}" } - = sub { exists shift->{$attribute} } - } - - if ($args{handles}) { - _has_handles($caller, $attribute, \%args); - } - - if (exists $args{init_arg}) { - $metadata_for{$caller}{$attribute}{init_arg} = $args{init_arg}; - } - } - }, - %exports, - ); - - # We keep this so code doing 'no Mo;' actually does a cleanup. - $export_for{$caller} = [ keys %exports ]; - - # Export has, extends and sosuch. - for my $keyword ( keys %exports ) { - *{ _glob_for "${caller}::$keyword" } = $exports{$keyword} - } - # Set up our caller's ISA, unless they already set it manually themselves, - # in which case we assume they know what they are doing. - # XXX weird syntax here because we want to call the classes' extends at - # least once, to avoid warnings. - *{ _glob_for "${caller}::extends" }{CODE}->( "Mo::Object" ) - unless @{ *{ _glob_for "${caller}::ISA" }{ARRAY} || [] }; -}; - -sub _check_type_constaints { - my ($attribute, $I, $I_name, $val) = @_; - ( ref($I) eq 'CODE' - ? $I->($val) - : (ref $val eq $I - || ($val && $val eq $I) - || (exists $TYPES{$I} && $TYPES{$I}->($val))) - ) - || Carp::confess( - qq - . qq - . (defined $val ? Mo::Dumper($val) : 'undef') ) -} - -# handles handles -sub _has_handles { - my ($caller, $attribute, $args) = @_; - my $handles = $args->{handles}; - - my $ref = ref $handles; - my $kv; - if ( $ref eq ref [] ) { - # handles => [ ... list of methods ... ], - $kv = { map { $_,$_ } @{$handles} }; - } - elsif ( $ref eq ref {} ) { - # handles => { 'method_to_install' => 'original_method' | [ 'original_method', ... curried arguments ... ], }, - $kv = $handles; - } - elsif ( $ref eq ref qr// ) { - # handles => qr/PAT/, - Carp::confess("Cannot delegate methods based on a Regexp without a type constraint (isa)") - unless $args->{isa}; - my $target_class = $args->{isa}; - $kv = { - map { $_, $_ } - grep { $_ =~ $handles } - grep { !exists $Mo::Object::{$_} && $target_class->can($_) } - grep { $_ ne 'has' && $_ ne 'extends' } - keys %{ _stash_for $target_class } - }; - } - else { - Carp::confess("handles for $ref not yet implemented"); - } - - while ( my ($method, $target) = each %{$kv} ) { - my $name = _glob_for "${caller}::$method"; - Carp::confess("You cannot overwrite a locally defined method ($method) with a delegation") - if defined &$name; - - # If we have an arrayref, they are currying some arguments. - my ($target, @curried_args) = ref($target) ? @$target : $target; - *$name = sub { - my $self = shift; - my $delegate_to = $self->$attribute(); - my $error = "Cannot delegate $method to $target because the value of $attribute"; - Carp::confess("$error is not defined") unless $delegate_to; - Carp::confess("$error is not an object (got '$delegate_to')") - unless Scalar::Util::blessed($delegate_to) || (!ref($delegate_to) && $delegate_to->can($target)); - return $delegate_to->$target(@curried_args, @_); - } - } -} - -# Nested (or parametized) constraints look like this: ArrayRef[CONSTRAINT] or -# Maybe[CONSTRAINT]. This function returns a coderef that implements one of -# these. -sub _nested_constraints { - my ($attribute, $aggregate_type, $type) = @_; - - my $inner_types; - if ( $type =~ /\A(ArrayRef|Maybe)\[(.*)\]\z/ ) { - # If the inner constraint -- the part within brackets -- is also a parametized - # constraint, then call this function recursively. - $inner_types = _nested_constraints($1, $2); - } - else { - # Otherwise, try checking if it's one of the built-in types. - $inner_types = $TYPES{$type}; - } - - if ( $aggregate_type eq 'ArrayRef' ) { - return sub { - my ($val) = @_; - return unless ref($val) eq ref([]); - - if ($inner_types) { - for my $value ( @{$val} ) { - return unless $inner_types->($value) - } - } - else { - # $inner_types isn't set, we are dealing with a class name. - for my $value ( @{$val} ) { - return unless $value && ($value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type))); - } - } - return 1; - }; - } - elsif ( $aggregate_type eq 'Maybe' ) { - return sub { - my ($value) = @_; - # For Maybe, undef is valid - return 1 if ! defined($value); - # Otherwise, defer to the inner type - if ($inner_types) { - return unless $inner_types->($value) - } - else { - return unless $value eq $type - || (Scalar::Util::blessed($value) && $value->isa($type)); - } - return 1; - } - } - else { - Carp::confess("Nested aggregate types are only implemented for ArrayRefs and Maybe"); - } -} - -# Sets a package's @ISA to the list passed in. Overwrites any previous values. -sub _set_package_isa { - my ($package, @new_isa) = @_; - - *{ _glob_for "${package}::ISA" } = [@new_isa]; -} - -# Each class has its own metadata. When a class inhyerits attributes, -# it should also inherit the attribute metadata. -sub _set_inherited_metadata { - my $class = shift; - my $linearized_isa = mro::get_linear_isa($class); - my %new_metadata; - - # Walk @ISA in reverse, grabbing the metadata for each - # class. Attributes with the same name defined in more - # specific classes override their parent's attributes. - for my $isa_class (reverse @$linearized_isa) { - %new_metadata = ( - %new_metadata, - %{ $metadata_for{$isa_class} || {} }, - ); - } - $metadata_for{$class} = \%new_metadata; -} - -sub unimport { - my $caller = scalar caller(); - my $stash = _stash_for( $caller ); - - delete $stash->{$_} for @{$export_for{$caller}}; -} - -sub Dumper { - require Data::Dumper; - local $Data::Dumper::Indent = 0; - local $Data::Dumper::Sortkeys = 0; - local $Data::Dumper::Quotekeys = 0; - local $Data::Dumper::Terse = 1; - - Data::Dumper::Dumper(@_) -} - -BEGIN { - # mro is the method resolution order. The module itself is core in - # recent Perls; In older Perls it's available from MRO::Compat from - # CPAN, and in case that isn't available to us, we inline the barest - # funcionality. - if ($] >= 5.010) { - { local $@; require mro; } - } - else { - local $@; - eval { - require MRO::Compat; - } or do { - *mro::get_linear_isa = *mro::get_linear_isa_dfs = sub { - no strict 'refs'; - - my $classname = shift; - - my @lin = ($classname); - my %stored; - foreach my $parent (@{"$classname\::ISA"}) { - my $plin = mro::get_linear_isa_dfs($parent); - foreach (@$plin) { - next if exists $stored{$_}; - push(@lin, $_); - $stored{$_} = 1; - } - } - return \@lin; - }; - } - } -} - -} -1; -# ########################################################################### -# End Mo package -# ########################################################################### diff --git a/lib/MockSth.pm b/lib/MockSth.pm index 0b04b7c7..9e6d6880 100644 --- a/lib/MockSth.pm +++ b/lib/MockSth.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/MockSync.pm b/lib/MockSync.pm index 41051caa..7e9ac297 100644 --- a/lib/MockSync.pm +++ b/lib/MockSync.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/MockSyncStream.pm b/lib/MockSyncStream.pm index a9ba9435..f06e6458 100644 --- a/lib/MockSyncStream.pm +++ b/lib/MockSyncStream.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/MySQLConfig.pm b/lib/MySQLConfig.pm index 20fe8ec7..c7064734 100644 --- a/lib/MySQLConfig.pm +++ b/lib/MySQLConfig.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/MySQLConfigComparer.pm b/lib/MySQLConfigComparer.pm index febd023f..c0e500a4 100644 --- a/lib/MySQLConfigComparer.pm +++ b/lib/MySQLConfigComparer.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/MySQLProtocolParser.pm b/lib/MySQLProtocolParser.pm index 64867bce..8b896467 100644 --- a/lib/MySQLProtocolParser.pm +++ b/lib/MySQLProtocolParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Percona Inc. +# This program is copyright 2007-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -340,6 +340,19 @@ sub parse_event { if ( $packet->{data_len} == 0 ) { PTDEBUG && _d('TCP control:', map { uc $_ } grep { $packet->{$_} } qw(syn ack fin rst)); + if ( $packet->{'fin'} + && ($session->{state} || '') eq 'server_handshake' ) { + PTDEBUG && _d('Client aborted connection'); + my $event = { + cmd => 'Admin', + arg => 'administrator command: Connect', + ts => $packet->{ts}, + }; + $session->{attribs}->{Error_msg} = 'Client closed connection during handshake'; + $event = $self->_make_event($event, $packet, $session); + delete $self->{sessions}->{$session->{client}}; + return $event; + } return; } @@ -612,7 +625,8 @@ sub _packet_from_server { } my $event; - if ( $session->{state} eq 'client_auth' ) { + if ( $session->{state} eq 'client_auth' + || $session->{state} eq 'server_handshake' ) { PTDEBUG && _d('Connection failed'); $event = { cmd => 'Admin', @@ -641,11 +655,14 @@ sub _packet_from_server { } $event = { - cmd => $com, - arg => $arg, - ts => $packet->{ts}, - Error_no => $error->{errno} ? "#$error->{errno}" : 'none', + cmd => $com, + arg => $arg, + ts => $packet->{ts}, }; + if ( $error->{errno} ) { + # https://bugs.launchpad.net/percona-toolkit/+bug/823411 + $event->{Error_no} = $error->{errno}; + } $session->{attribs}->{Error_msg} = $error->{message}; return $self->_make_event($event, $packet, $session); } @@ -902,13 +919,18 @@ sub _make_event { Thread_id => $session->{thread_id}, pos_in_log => $session->{pos_in_log}, Query_time => timestamp_diff($session->{ts}, $packet->{ts}), - Error_no => $event->{Error_no} || 'none', Rows_affected => ($event->{Rows_affected} || 0), Warning_count => ($event->{Warning_count} || 0), No_good_index_used => ($event->{No_good_index_used} ? 'Yes' : 'No'), No_index_used => ($event->{No_index_used} ? 'Yes' : 'No'), }; @{$new_event}{keys %{$session->{attribs}}} = values %{$session->{attribs}}; + # https://bugs.launchpad.net/percona-toolkit/+bug/823411 + foreach my $opt_attrib ( qw(Error_no) ) { + if ( defined $event->{$opt_attrib} ) { + $new_event->{$opt_attrib} = $event->{$opt_attrib}; + } + } PTDEBUG && _d('Properties of event:', Dumper($new_event)); # Delete cmd to prevent re-making the same event if the @@ -1070,9 +1092,17 @@ sub parse_error_packet { } my $errno = to_num(substr($data, 0, 4)); my $marker = to_string(substr($data, 4, 2)); - return unless $marker eq '#'; - my $sqlstate = to_string(substr($data, 6, 10)); - my $message = to_string(substr($data, 16)); + my $sqlstate = ''; + my $message = ''; + if ( $marker eq '#' ) { + $sqlstate = to_string(substr($data, 6, 10)); + $message = to_string(substr($data, 16)); + } + else { + $marker = ''; + $message = to_string(substr($data, 4)); + } + return unless $message; my $pkt = { errno => $errno, sqlstate => $marker . $sqlstate, diff --git a/lib/MySQLStatusWaiter.pm b/lib/MySQLStatusWaiter.pm index f87a9841..ab5bfa55 100644 --- a/lib/MySQLStatusWaiter.pm +++ b/lib/MySQLStatusWaiter.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/NibbleIterator.pm b/lib/NibbleIterator.pm index c8c03405..7edabdc3 100644 --- a/lib/NibbleIterator.pm +++ b/lib/NibbleIterator.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/OobNibbleIterator.pm b/lib/OobNibbleIterator.pm index a98b5cc8..c1204023 100644 --- a/lib/OobNibbleIterator.pm +++ b/lib/OobNibbleIterator.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/OptionParser.pm b/lib/OptionParser.pm index 58496ff4..938aaff0 100644 --- a/lib/OptionParser.pm +++ b/lib/OptionParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Outfile.pm b/lib/Outfile.pm index b940da6e..6583c0a4 100644 --- a/lib/Outfile.pm +++ b/lib/Outfile.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Percona/Toolkit.pm b/lib/Percona/Toolkit.pm index 252ede7a..cec5f22d 100644 --- a/lib/Percona/Toolkit.pm +++ b/lib/Percona/Toolkit.pm @@ -19,7 +19,7 @@ # ########################################################################### { package Percona::Toolkit; -our $VERSION = '2.1.7'; +our $VERSION = '2.1.8'; 1; } diff --git a/lib/Percona/XtraDB/Cluster.pm b/lib/Percona/XtraDB/Cluster.pm index ee3c3c0c..a0d2d13d 100644 --- a/lib/Percona/XtraDB/Cluster.pm +++ b/lib/Percona/XtraDB/Cluster.pm @@ -27,7 +27,7 @@ use warnings FATAL => 'all'; use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; -use Mo; +use Lmo; use Data::Dumper; sub get_cluster_name { diff --git a/lib/PerconaTest.pm b/lib/PerconaTest.pm index a067bd1d..5da730b4 100644 --- a/lib/PerconaTest.pm +++ b/lib/PerconaTest.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -58,7 +58,6 @@ our @EXPORT = qw( wait_until wait_for wait_until_slave_running - wait_until_no_lag test_log_parser test_protocol_parser test_packet_parser @@ -325,6 +324,39 @@ sub wait_for_sh { ); }; +sub kill_program { + my (%args) = @_; + + my $pid_file = $args{pid_file}; + my $pid = $args{pid}; + + if ( $pid_file ) { + chomp($pid = `cat $pid_file 2>/dev/null`); + } + + if ( $pid ) { + PTDEVDEBUG && _d('Killing PID', $pid); + kill(15, $pid); + wait_until( + sub { my $is_alive = kill(0, $pid); return !$is_alive; }, + 1.5, # sleep between tries + 15, # max time to try + ); + if ( kill(0, $pid) ) { + warn "PID $pid did not die; using kill -9\n"; + kill(9, $pid); + } + } + else { + PTDEVDEBUG && _d('No PID to kill'); + } + + if ( $pid_file && -f $pid_file ) { + PTDEVDEBUG && _d('Removing PID file', $pid_file); + unlink $pid_file; + } +} + sub not_running { my ($cmd) = @_; PTDEVDEBUG && _d('Wait until not running:', $cmd); diff --git a/lib/PgLogParser.pm b/lib/PgLogParser.pm index c1b4d733..8ac78e1d 100644 --- a/lib/PgLogParser.pm +++ b/lib/PgLogParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2010-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Pingback.pm b/lib/Pingback.pm index 84a4803f..0f7a352e 100644 --- a/lib/Pingback.pm +++ b/lib/Pingback.pm @@ -1,4 +1,4 @@ -# This program is copyright 2012 Percona Inc. +# This program is copyright 2012 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -15,7 +15,7 @@ # this program; if not, write to the Free Software Foundation, Inc., 59 Temple # Place, Suite 330, Boston, MA 02111-1307 USA. # ########################################################################### -# VersionCheck package +# Pingback package # ########################################################################### { # Package: Pingback @@ -51,7 +51,6 @@ local $EVAL_ERROR; eval { require Percona::Toolkit; require HTTPMicro; - require VersionCheck; }; sub version_check { @@ -137,10 +136,9 @@ sub pingback { my ($url) = @args{@required_args}; # Optional args - my ($instances, $ua, $vc) = @args{qw(instances ua VersionCheck)}; + my ($instances, $ua) = @args{qw(instances ua)}; $ua ||= HTTPMicro->new( timeout => 5 ); - $vc ||= VersionCheck->new(); # GET https://upgrade.percona.com, the server will return # a plaintext list of items/programs it wants the tool @@ -165,7 +163,7 @@ sub pingback { # type => "mysql_variables", # vars => ["version", "version_comment"], # } - my $items = $vc->parse_server_response( + my $items = __PACKAGE__->parse_server_response( response => $response->{content} ); die "Failed to parse server requested programs: $response->{content}" @@ -174,7 +172,7 @@ sub pingback { # Get the versions for those items in another hashref also keyed on # the items like: # "MySQL" => "MySQL Community Server 5.1.49-log", - my $versions = $vc->get_versions( + my $versions = __PACKAGE__->get_versions( items => $items, instances => $instances, ); @@ -212,7 +210,7 @@ sub pingback { # If the server has suggestions for items, it sends them back in # the same format: ITEM:TYPE:SUGGESTION\n. ITEM:TYPE is mostly for # debugging; the tool just repports the suggestions. - $items = $vc->parse_server_response( + $items = __PACKAGE__->parse_server_response( response => $response->{content}, split_vars => 0, ); @@ -424,6 +422,256 @@ sub validate_options { . join(", ", @values[0..$#values-1]) . " and $values[-1]" ); } +sub parse_server_response { + my ($self, %args) = @_; + my @required_args = qw(response); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($response) = @args{@required_args}; + + my %items = map { + my ($item, $type, $vars) = split(";", $_); + if ( !defined $args{split_vars} || $args{split_vars} ) { + $vars = [ split(",", ($vars || '')) ]; + } + $item => { + item => $item, + type => $type, + vars => $vars, + }; + } split("\n", $response); + + PTDEBUG && _d('Items:', Dumper(\%items)); + + return \%items; +} + +sub get_versions { + my ($self, %args) = @_; + my @required_args = qw(items); + foreach my $arg ( @required_args ) { + die "I need a $arg arugment" unless $args{$arg}; + } + my ($items) = @args{@required_args}; + + my %versions; + foreach my $item ( values %$items ) { + next unless $self->valid_item($item); + + eval { + my $func = 'get_' . $item->{type}; + my $version = $self->$func( + item => $item, + instances => $args{instances}, + ); + if ( $version ) { + chomp $version unless ref($version); + $versions{$item->{item}} = $version; + } + }; + if ( $EVAL_ERROR ) { + PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); + } + } + + return \%versions; +} + +sub valid_item { + my ($self, $item) = @_; + return unless $item; + + if ( ($item->{type} || '') !~ m/ + ^(?: + os_version + |perl_version + |perl_module_version + |mysql_variable + |bin_version + )$/x ) { + PTDEBUG && _d('Invalid type:', $item->{type}); + return; + } + + return 1; +} + +sub get_os_version { + my ($self) = @_; + + if ( $OSNAME eq 'MSWin32' ) { + require Win32; + return Win32::GetOSDisplayName(); + } + + chomp(my $platform = `uname -s`); + PTDEBUG && _d('platform:', $platform); + return $OSNAME unless $platform; + + chomp(my $lsb_release + = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); + PTDEBUG && _d('lsb_release:', $lsb_release); + + my $release = ""; + + if ( $platform eq 'Linux' ) { + if ( -f "/etc/fedora-release" ) { + $release = `cat /etc/fedora-release`; + } + elsif ( -f "/etc/redhat-release" ) { + $release = `cat /etc/redhat-release`; + } + elsif ( -f "/etc/system-release" ) { + $release = `cat /etc/system-release`; + } + elsif ( $lsb_release ) { + $release = `$lsb_release -ds`; + } + elsif ( -f "/etc/lsb-release" ) { + $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; + $release =~ s/^\w+="([^"]+)".+/$1/; + } + elsif ( -f "/etc/debian_version" ) { + chomp(my $rel = `cat /etc/debian_version`); + $release = "Debian $rel"; + if ( -f "/etc/apt/sources.list" ) { + chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); + $release .= " ($code_name)" if $code_name; + } + } + elsif ( -f "/etc/os-release" ) { # openSUSE + chomp($release = `grep PRETTY_NAME /etc/os-release`); + $release =~ s/^PRETTY_NAME="(.+)"$/$1/; + } + elsif ( `ls /etc/*release 2>/dev/null` ) { + if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { + $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; + } + else { + $release = `cat /etc/*release | head -n1`; + } + } + } + elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { + my $rel = `uname -r`; + $release = "$platform $rel"; + } + elsif ( $platform eq "SunOS" ) { + my $rel = `head -n1 /etc/release` || `uname -r`; + $release = "$platform $rel"; + } + + if ( !$release ) { + PTDEBUG && _d('Failed to get the release, using platform'); + $release = $platform; + } + chomp($release); + + # For Gentoo, which returns a value in quotes + $release =~ s/^"|"$//g; + + PTDEBUG && _d('OS version =', $release); + return $release; +} + +sub get_perl_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + my $version = sprintf '%vd', $PERL_VERSION; + PTDEBUG && _d('Perl version', $version); + return $version; +} + +sub get_perl_module_version { + my ($self, %args) = @_; + my $item = $args{item}; + return unless $item; + + # If there's a var, then its an explicit Perl variable name to get, + # else the item name is an implicity Perl module name to which we + # append ::VERSION to get the module's version. + my $var = $item->{item} . '::VERSION'; + my $version = _get_scalar($var); + PTDEBUG && _d('Perl version for', $var, '=', "$version"); + + # Explicitly stringify this else $PERL_VERSION will return + # as a version object. + return $version ? "$version" : $version; +} + +sub _get_scalar { + no strict; + return ${*{shift()}}; +} + +sub get_mysql_variable { + my $self = shift; + return $self->_get_from_mysql( + show => 'VARIABLES', + @_, + ); +} + +sub _get_from_mysql { + my ($self, %args) = @_; + my $show = $args{show}; + my $item = $args{item}; + my $instances = $args{instances}; + return unless $show && $item; + + if ( !$instances || !@$instances ) { + if ( $ENV{PTVCDEBUG} || PTDEBUG ) { + _d('Cannot check', $item, 'because there are no MySQL instances'); + } + return; + } + + my @versions; + my %version_for; + foreach my $instance ( @$instances ) { + my $dbh = $instance->{dbh}; + local $dbh->{FetchHashKeyName} = 'NAME_lc'; + my $sql = qq/SHOW $show/; + PTDEBUG && _d($sql); + my $rows = $dbh->selectall_hashref($sql, 'variable_name'); + + my @versions; + foreach my $var ( @{$item->{vars}} ) { + $var = lc($var); + my $version = $rows->{$var}->{value}; + PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, + 'on', $instance->{name}); + push @versions, $version; + } + + $version_for{ $instance->{id} } = join(' ', @versions); + } + + return \%version_for; +} + +sub get_bin_version { + my ($self, %args) = @_; + my $item = $args{item}; + my $cmd = $item->{item}; + return unless $cmd; + + my $sanitized_command = File::Basename::basename($cmd); + PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); + return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; + + my $output = `$sanitized_command --version 2>&1`; + PTDEBUG && _d('output:', $output); + + my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; + + PTDEBUG && _d('Version for', $sanitized_command, '=', $version); + return $version; +} + sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } diff --git a/lib/Pipeline.pm b/lib/Pipeline.pm index 9a890716..1f50afbf 100644 --- a/lib/Pipeline.pm +++ b/lib/Pipeline.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -42,7 +42,7 @@ sub new { my $self = { # default values for optional args - instrument => 0, + instrument => PTDEBUG, continue_on_error => 0, # specified arg values override defaults @@ -71,9 +71,7 @@ sub add { push @{$self->{procs}}, $process; push @{$self->{names}}, $name; - if ( my $n = $args{retry_on_error} ) { - $self->{retries}->{$name} = $n; - } + $self->{retries}->{$name} = $args{retry_on_error} || 100; if ( $self->{instrument} ) { $self->{instrumentation}->{$name} = { time => 0, calls => 0 }; } @@ -163,7 +161,11 @@ sub execute { my $msg = "Pipeline process " . ($procno + 1) . " ($name) caused an error: " . $EVAL_ERROR; - if ( defined $self->{retries}->{$name} ) { + if ( !$self->{continue_on_error} ) { + die $msg . "Terminating pipeline because --continue-on-error " + . "is false.\n"; + } + elsif ( defined $self->{retries}->{$name} ) { my $n = $self->{retries}->{$name}; if ( $n ) { warn $msg . "Will retry pipeline process $procno ($name) " @@ -175,9 +177,6 @@ sub execute { . "($name) caused too many errors.\n"; } } - elsif ( !$self->{continue_on_error} ) { - die $msg; - } else { warn $msg; } diff --git a/lib/PodParser.pm b/lib/PodParser.pm index c6475eb1..4da7df2f 100644 --- a/lib/PodParser.pm +++ b/lib/PodParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Processlist.pm b/lib/Processlist.pm index 015b8508..e53eca3b 100644 --- a/lib/Processlist.pm +++ b/lib/Processlist.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2008-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Progress.pm b/lib/Progress.pm index 54b47b12..07ad4f4c 100644 --- a/lib/Progress.pm +++ b/lib/Progress.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/ProtocolParser.pm b/lib/ProtocolParser.pm index d8aaa544..a733e673 100644 --- a/lib/ProtocolParser.pm +++ b/lib/ProtocolParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/QueryAdvisorRules.pm b/lib/QueryAdvisorRules.pm index 3d4cddc1..ad315ef2 100644 --- a/lib/QueryAdvisorRules.pm +++ b/lib/QueryAdvisorRules.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/QueryParser.pm b/lib/QueryParser.pm index 90c6e7d0..b6f56f20 100644 --- a/lib/QueryParser.pm +++ b/lib/QueryParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2011 Percona Inc. +# This program is copyright 2008-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/QueryReportFormatter.pm b/lib/QueryReportFormatter.pm index 95eff7c2..fd783ffc 100644 --- a/lib/QueryReportFormatter.pm +++ b/lib/QueryReportFormatter.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2011 Percona Inc. +# This program is copyright 2008-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -29,8 +29,7 @@ # which is also in mk-query-digest. package QueryReportFormatter; -use strict; -use warnings FATAL => 'all'; +use Lmo; use English qw(-no_match_vars); use POSIX qw(floor); @@ -43,6 +42,9 @@ use constant PTDEBUG => $ENV{PTDEBUG} || 0; use constant LINE_LENGTH => 74; use constant MAX_STRING_LENGTH => 10; +{ local $EVAL_ERROR; eval { require Quoter } }; +{ local $EVAL_ERROR; eval { require ReportFormatter } }; + # Sub: new # # Parameters: @@ -56,31 +58,69 @@ use constant MAX_STRING_LENGTH => 10; # Optional arguments: # QueryReview - object used in # dbh - dbh used in -# ExplainAnalyzer - object used in . -# This causes a sparkline to be printed (issue 1141). # # Returns: # QueryReportFormatter object -sub new { - my ( $class, %args ) = @_; - foreach my $arg ( qw(OptionParser QueryRewriter Quoter) ) { - die "I need a $arg argument" unless $args{$arg}; +has Quoter => ( + is => 'ro', + isa => 'Quoter', + default => sub { Quoter->new() }, +); + +has label_width => ( + is => 'ro', + isa => 'Int', +); + +has global_headers => ( + is => 'ro', + isa => 'ArrayRef', + default => sub { [qw( total min max avg 95% stddev median)] }, +); + +has event_headers => ( + is => 'ro', + isa => 'ArrayRef', + default => sub { [qw(pct total min max avg 95% stddev median)] }, +); + +has ReportFormatter => ( + is => 'ro', + isa => 'ReportFormatter', + builder => '_build_report_formatter', +); + +sub _build_report_formatter { + return ReportFormatter->new( + line_width => LINE_LENGTH, + extend_right => 1, + ); +} + +sub BUILDARGS { + my $class = shift; + my $args = $class->SUPER::BUILDARGS(@_); + + foreach my $arg ( qw(OptionParser QueryRewriter) ) { + die "I need a $arg argument" unless $args->{$arg}; } # If ever someone wishes for a wider label width. - my $label_width = $args{label_width} || 12; + my $label_width = $args->{label_width} ||= 12; PTDEBUG && _d('Label width:', $label_width); - my $cheat_width = $label_width + 1; - + my $o = delete $args->{OptionParser}; my $self = { - %args, - label_width => $label_width, + %$args, + options => { + show_all => $o->get('show-all'), + shorten => $o->get('shorten'), + report_all => $o->get('report-all'), + report_histogram => $o->get('report-histogram'), + }, num_format => "# %-${label_width}s %3s %7s %7s %7s %7s %7s %7s %7s", bool_format => "# %-${label_width}s %3d%% yes, %3d%% no", string_format => "# %-${label_width}s %s", - global_headers => [qw( total min max avg 95% stddev median)], - event_headers => [qw(pct total min max avg 95% stddev median)], hidden_attrib => { # Don't sort/print these attribs in the reports. arg => 1, # They're usually handled specially, or not fingerprint => 1, # printed at all. @@ -88,32 +128,7 @@ sub new { ts => 1, }, }; - return bless $self, $class; -} - -# Sub: set_report_formatter -# Set a report formatter object for a report. By default this package will -# instantiate ReportFormatter objects to format columnized reports (e.g. -# for profile and prepared reports). Setting a caller-created formatter -# object (usually a obj) is used for tested and also by -# to extend the profile report line width to 82 for -# the --explain sparkline. -# -# Parameters: -# %args - Arguments -# -# Required Arguments: -# report - Report name, e.g. profile, prepared, etc. -# formatter - Formatter object, usually a obj -sub set_report_formatter { - my ( $self, %args ) = @_; - my @required_args = qw(report formatter); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless exists $args{$arg}; - } - my ($report, $formatter) = @args{@required_args}; - $self->{formatter_for}->{$report} = $formatter; - return; + return $self; } # Arguments: @@ -243,7 +258,7 @@ sub header { shorten(scalar keys %{$results->{classes}}, d=>1_000), shorten($qps || 0, d=>1_000), shorten($conc || 0, d=>1_000)); - $line .= ('_' x (LINE_LENGTH - length($line) + $self->{label_width} - 12)); + $line .= ('_' x (LINE_LENGTH - length($line) + $self->label_width() - 12)); push @result, $line; # Second line: time range @@ -308,6 +323,70 @@ sub header { return join("\n", map { s/\s+$//; $_ } @result) . "\n"; } +sub query_report_values { + my ($self, %args) = @_; + foreach my $arg ( qw(ea worst orderby groupby) ) { + die "I need a $arg argument" unless defined $arg; + } + my $ea = $args{ea}; + my $groupby = $args{groupby}; + my $worst = $args{worst}; + + my $q = $self->Quoter; + my $qv = $self->{QueryReview}; + my $qr = $self->{QueryRewriter}; + + my @values; + # Print each worst item: its stats/metrics (sum/min/max/95%/etc.), + # Query_time distro chart, tables, EXPLAIN, fingerprint, etc. + # Items are usually unique queries/fingerprints--depends on how + # the events were grouped. + ITEM: + foreach my $top_event ( @$worst ) { + my $item = $top_event->[0]; + my $reason = $args{explain_why} ? $top_event->[1] : ''; + my $rank = $top_event->[2]; + my $stats = $ea->results->{classes}->{$item}; + my $sample = $ea->results->{samples}->{$item}; + my $samp_query = $sample->{arg} || ''; + + my %item_vals = ( + item => $item, + samp_query => $samp_query, + rank => ($rank || 0), + reason => $reason, + ); + + # ############################################################### + # Possibly skip item for --review. + # ############################################################### + my $review_vals; + if ( $qv ) { + $review_vals = $qv->get_review_info($item); + next ITEM if $review_vals->{reviewed_by} && !$self->{options}->{report_all}; + for my $col ( $qv->review_cols() ) { + push @{$item_vals{review_vals}}, [$col, $review_vals->{$col}]; + } + } + + $item_vals{default_db} = $sample->{db} ? $sample->{db} + : $stats->{db}->{unq} ? keys %{$stats->{db}->{unq}} + : undef; + $item_vals{tables} = [$self->{QueryParser}->extract_tables( + query => $samp_query, + default_db => $item_vals{default_db}, + Quoter => $self->Quoter, + )]; + + if ( $samp_query && ($args{variations} && @{$args{variations}}) ) { + $item_vals{crc} = crc32($samp_query); + } + + push @values, \%item_vals; + } + return \@values; +} + # Arguments: # * ea obj: EventAggregator # * worst arrayref: worst items @@ -319,16 +398,11 @@ sub header { # * print_header bool: "Report grouped by" header sub query_report { my ( $self, %args ) = @_; - foreach my $arg ( qw(ea worst orderby groupby) ) { - die "I need a $arg argument" unless defined $arg; - } + my $ea = $args{ea}; my $groupby = $args{groupby}; - my $worst = $args{worst}; + my $report_values = $self->query_report_values(%args); - my $o = $self->{OptionParser}; - my $q = $self->{Quoter}; - my $qv = $self->{QueryReview}; my $qr = $self->{QueryRewriter}; my $report = ''; @@ -350,66 +424,36 @@ sub query_report { # Items are usually unique queries/fingerprints--depends on how # the events were grouped. ITEM: - foreach my $top_event ( @$worst ) { - my $item = $top_event->[0]; - my $reason = $args{explain_why} ? $top_event->[1] : ''; - my $rank = $top_event->[2]; - my $stats = $ea->results->{classes}->{$item}; - my $sample = $ea->results->{samples}->{$item}; - my $samp_query = $sample->{arg} || ''; - - # ############################################################### - # Possibly skip item for --review. - # ############################################################### - my $review_vals; - if ( $qv ) { - $review_vals = $qv->get_review_info($item); - next ITEM if $review_vals->{reviewed_by} && !$o->get('report-all'); - } - - # ############################################################### - # Get tables for --for-explain. - # ############################################################### - my ($default_db) = $sample->{db} ? $sample->{db} - : $stats->{db}->{unq} ? keys %{$stats->{db}->{unq}} - : undef; - my @tables; - if ( $o->get('for-explain') ) { - @tables = $self->{QueryParser}->extract_tables( - query => $samp_query, - default_db => $default_db, - Quoter => $self->{Quoter}, - ); - } - + foreach my $vals ( @$report_values ) { + my $item = $vals->{item}; # ############################################################### # Print the standard query analysis report. # ############################################################### - $report .= "\n" if $rank > 1; # space between each event report + $report .= "\n" if $vals->{rank} > 1; # space between each event report $report .= $self->event_report( %args, item => $item, - sample => $sample, - rank => $rank, - reason => $reason, + sample => $ea->results->{samples}->{$item}, + rank => $vals->{rank}, + reason => $vals->{reason}, attribs => $attribs, - db => $default_db, + db => $vals->{default_db}, ); - if ( $o->get('report-histogram') ) { + if ( $self->{options}->{report_histogram} ) { $report .= $self->chart_distro( %args, - attrib => $o->get('report-histogram'), - item => $item, + attrib => $self->{options}->{report_histogram}, + item => $vals->{item}, ); } - if ( $qv && $review_vals ) { + if ( $vals->{review_vals} ) { # Print the review information that is already in the table # before putting anything new into the table. $report .= "# Review information\n"; - foreach my $col ( $qv->review_cols() ) { - my $val = $review_vals->{$col}; + foreach my $elem ( @{$vals->{review_vals}} ) { + my ($col, $val) = @$elem; if ( !$val || $val ne '0000-00-00 00:00:00' ) { # issue 202 $report .= sprintf "# %13s: %-s\n", $col, ($val ? $val : ''); } @@ -418,25 +462,22 @@ sub query_report { if ( $groupby eq 'fingerprint' ) { # Shorten it if necessary (issue 216 and 292). - $samp_query = $qr->shorten($samp_query, $o->get('shorten')) - if $o->get('shorten'); + my $samp_query = $qr->shorten($vals->{samp_query}, $self->{options}->{shorten}) + if $self->{options}->{shorten}; # Print query fingerprint. - $report .= "# Fingerprint\n# $item\n" - if $o->get('fingerprints'); + PTDEBUG && _d("Fingerprint\n# $vals->{item}\n"); # Print tables used by query. - $report .= $self->tables_report(@tables) - if $o->get('for-explain'); + $report .= $self->tables_report(@{$vals->{tables}}); # Print sample (worst) query's CRC % 1_000. We mod 1_000 because # that's actually the value stored in the ea, not the full checksum. # So the report will print something like, # # arg crc 685 (2/66%), 159 (1/33%) # Thus we want our "CRC" line to be 685 and not 18547302820. - if ( $samp_query && ($args{variations} && @{$args{variations}}) ) { - my $crc = crc32($samp_query); - $report.= "# CRC " . ($crc ? $crc % 1_000 : "") . "\n"; + if ( $vals->{crc} ) { + $report.= "# CRC " . ($vals->{crc} % 1_000) . "\n"; } my $log_type = $args{log_type} || ''; @@ -450,14 +491,13 @@ sub query_report { } else { $report .= "# EXPLAIN /*!50100 PARTITIONS*/\n$samp_query${mark}\n"; - $report .= $self->explain_report($samp_query, $default_db); + $report .= $self->explain_report($samp_query, $vals->{default_db}); } } else { $report .= "$samp_query${mark}\n"; my $converted = $qr->convert_to_select($samp_query); - if ( $o->get('for-explain') - && $converted + if ( $converted && $converted =~ m/^[\(\s]*select/i ) { # It converted OK to a SELECT $report .= "# Converted for EXPLAIN\n# EXPLAIN /*!50100 PARTITIONS*/\n$converted${mark}\n"; @@ -466,7 +506,7 @@ sub query_report { } else { if ( $groupby eq 'tables' ) { - my ( $db, $tbl ) = $q->split_unquote($item); + my ( $db, $tbl ) = $self->Quoter->split_unquote($item); $report .= $self->tables_report([$db, $tbl]); } $report .= "$item\n"; @@ -486,21 +526,20 @@ sub query_report { # * rank scalar: item rank among the worst # Print a report about the statistics in the EventAggregator. # Called by query_report(). -sub event_report { - my ( $self, %args ) = @_; - foreach my $arg ( qw(ea item orderby) ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my $ea = $args{ea}; - my $item = $args{item}; +sub event_report_values { + my ($self, %args) = @_; + + my $ea = $args{ea}; + my $item = $args{item}; my $orderby = $args{orderby}; my $results = $ea->results(); - my $o = $self->{OptionParser}; - my @result; + + my %vals; # Return unless the item exists in the results (it should). my $store = $results->{classes}->{$item}; - return "# No such event $item\n" unless $store; + + return unless $store; # Pick the first attribute to get counts my $global_cnt = $results->{globals}->{$orderby}->{cnt}; @@ -521,80 +560,26 @@ sub event_report { }; } - # First line like: - # Query 1: 9 QPS, 0x concurrency, ID 0x7F7D57ACDD8A346E at byte 5 ________ - my $line = sprintf( - '# %s %d: %s QPS, %sx concurrency, ID 0x%s at byte %.f ', - ($ea->{groupby} eq 'fingerprint' ? 'Query' : 'Item'), - $args{rank} || 0, - shorten($qps || 0, d=>1_000), - shorten($conc || 0, d=>1_000), - make_checksum($item), - $results->{samples}->{$item}->{pos_in_log} || 0, - ); - $line .= ('_' x (LINE_LENGTH - length($line) + $self->{label_width} - 12)); - push @result, $line; - - # Second line: reason why this class is being reported. - if ( $args{reason} ) { - push @result, - "# This item is included in the report because it matches " - . ($args{reason} eq 'top' ? '--limit.' : '--outliers.'); - } - - # Third line: Apdex and variance-to-mean (V/M) ratio, like: - # Scores: Apdex = 0.93 [1.0], V/M = 1.5 - { + $vals{groupby} = $ea->{groupby}; + $vals{qps} = $qps || 0; + $vals{concurrency} = $conc || 0; + $vals{checksum} = make_checksum($item); + $vals{pos_in_log} = $results->{samples}->{$item}->{pos_in_log} || 0; + $vals{reason} = $args{reason}; + $vals{variance_to_mean} = do { my $query_time = $ea->metrics(where => $item, attrib => 'Query_time'); - push @result, - sprintf("# Scores: Apdex = %s [%3.1f]%s, V/M = %.2f", - (defined $query_time->{apdex} ? "$query_time->{apdex}" : "NS"), - ($query_time->{apdex_t} || 0), - ($query_time->{cnt} < 100 ? "*" : ""), - ($query_time->{stddev}**2 / ($query_time->{avg} || 1)), - ); + $query_time->{stddev}**2 / ($query_time->{avg} || 1) + }; + + $vals{counts} = { + class_cnt => $class_cnt, + global_cnt => $global_cnt, + }; + + if ( my $ts = $store->{ts}) { + $vals{time_range} = $self->format_time_range($ts) || "unknown"; } - # Fourth line: EXPLAIN sparkline if --explain. - if ( $o->get('explain') && $results->{samples}->{$item}->{arg} ) { - eval { - my $sparkline = $self->explain_sparkline( - $results->{samples}->{$item}->{arg}, $args{db}); - push @result, "# EXPLAIN sparkline: $sparkline\n"; - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d("Failed to get EXPLAIN sparkline:", $EVAL_ERROR); - } - } - - if ( my $attrib = $o->get('report-histogram') ) { - my $sparkline = $self->distro_sparkline( - %args, - attrib => $attrib, - item => $item, - ); - if ( $sparkline ) { - # I find the | | bookends help make the sparkchart graph more clear. - # Else with just .^- it's difficult to tell where the chart beings - # or ends. - push @result, "# $attrib sparkline: |$sparkline|"; - } - } - - # Last line before column headers: time range - if ( my $ts = $store->{ts} ) { - my $time_range = $self->format_time_range($ts) || "unknown"; - push @result, "# Time range: $time_range"; - } - - # Column header line - push @result, $self->make_event_header(); - - # Count line - push @result, - sprintf $self->{num_format}, 'Count', - percentage_of($class_cnt, $global_cnt), $class_cnt, map { '' } (1..8); - # Sort the attributes, removing any hidden attributes, if they're not # already given to us. In mk-query-digest, this sub is called from # query_report(), but in testing it's called directly. query_report() @@ -607,11 +592,10 @@ sub event_report { ); } + $vals{attributes} = { map { $_ => [] } qw(num innodb bool string) }; + foreach my $type ( qw(num innodb) ) { # Add "InnoDB:" sub-header before grouped InnoDB_* attributes. - if ( $type eq 'innodb' && @{$attribs->{$type}} ) { - push @result, "# InnoDB:"; - }; NUM_ATTRIB: foreach my $attrib ( @{$attribs->{$type}} ) { @@ -631,15 +615,12 @@ sub event_report { $pct = percentage_of( $vals->{sum}, $results->{globals}->{$attrib}->{sum}); - push @result, - sprintf $self->{num_format}, - $self->make_label($attrib), $pct, @values; + push @{$vals{attributes}{$type}}, + [ $attrib, $pct, @values ]; } } if ( @{$attribs->{bool}} ) { - push @result, "# Boolean:"; - my $printed_bools = 0; BOOL_ATTRIB: foreach my $attrib ( @{$attribs->{bool}} ) { next BOOL_ATTRIB unless exists $store->{$attrib}; @@ -647,33 +628,125 @@ sub event_report { next unless scalar %$vals; if ( $vals->{sum} > 0 ) { - push @result, - sprintf $self->{bool_format}, - $self->make_label($attrib), $self->bool_percents($vals); - $printed_bools = 1; + push @{$vals{attributes}{bool}}, + [ $attrib, $self->bool_percents($vals) ]; } } - pop @result unless $printed_bools; } if ( @{$attribs->{string}} ) { - push @result, "# String:"; - my $printed_strings = 0; STRING_ATTRIB: foreach my $attrib ( @{$attribs->{string}} ) { next STRING_ATTRIB unless exists $store->{$attrib}; my $vals = $store->{$attrib}; next unless scalar %$vals; + push @{$vals{attributes}{string}}, + [ $attrib, $vals ]; + } + } + + + return \%vals; +} + +# TODO I maybe've broken the groupby report + +sub event_report { + my ( $self, %args ) = @_; + foreach my $arg ( qw(ea item orderby) ) { + die "I need a $arg argument" unless defined $args{$arg}; + } + + my $item = $args{item}; + my $val = $self->event_report_values(%args); + my @result; + + return "# No such event $item\n" unless $val; + + # First line like: + # Query 1: 9 QPS, 0x concurrency, ID 0x7F7D57ACDD8A346E at byte 5 ________ + my $line = sprintf( + '# %s %d: %s QPS, %sx concurrency, ID 0x%s at byte %.f ', + ($val->{groupby} eq 'fingerprint' ? 'Query' : 'Item'), + $args{rank} || 0, + shorten($val->{qps}, d=>1_000), + shorten($val->{concurrency}, d=>1_000), + $val->{checksum}, + $val->{pos_in_log}, + ); + $line .= ('_' x (LINE_LENGTH - length($line) + $self->label_width() - 12)); + push @result, $line; + + # Second line: reason why this class is being reported. + if ( $val->{reason} ) { + push @result, + "# This item is included in the report because it matches " + . ($val->{reason} eq 'top' ? '--limit.' : '--outliers.'); + } + + # Third line: Variance-to-mean (V/M) ratio, like: + # Scores: V/M = 1.5 + push @result, + sprintf("# Scores: V/M = %.2f", $val->{variance_to_mean} ); + + # Last line before column headers: time range + if ( $val->{time_range} ) { + push @result, "# Time range: $val->{time_range}"; + } + + # Column header line + push @result, $self->make_event_header(); + + # Count line + push @result, + sprintf $self->{num_format}, 'Count', + percentage_of($val->{counts}{class_cnt}, $val->{counts}{global_cnt}), + $val->{counts}{class_cnt}, + map { '' } (1..8); + + + my $attribs = $val->{attributes}; + + foreach my $type ( qw(num innodb) ) { + # Add "InnoDB:" sub-header before grouped InnoDB_* attributes. + if ( $type eq 'innodb' && @{$attribs->{$type}} ) { + push @result, "# InnoDB:"; + }; + + NUM_ATTRIB: + foreach my $attrib ( @{$attribs->{$type}} ) { + my ($attrib_name, @vals) = @$attrib; + push @result, + sprintf $self->{num_format}, + $self->make_label($attrib_name), @vals; + } + } + + if ( @{$attribs->{bool}} ) { + push @result, "# Boolean:"; + BOOL_ATTRIB: + foreach my $attrib ( @{$attribs->{bool}} ) { + my ($attrib_name, @vals) = @$attrib; + push @result, + sprintf $self->{bool_format}, + $self->make_label($attrib_name), @vals; + } + } + + if ( @{$attribs->{string}} ) { + push @result, "# String:"; + STRING_ATTRIB: + foreach my $attrib ( @{$attribs->{string}} ) { + my ($attrib_name, $vals) = @$attrib; push @result, sprintf $self->{string_format}, - $self->make_label($attrib), - $self->format_string_list($attrib, $vals, $class_cnt); - $printed_strings = 1; + $self->make_label($attrib_name), + $self->format_string_list($attrib_name, $vals, $val->{counts}{class_cnt}); } - pop @result unless $printed_strings; } + return join("\n", map { s/\s+$//; $_ } @result) . "\n"; } @@ -739,98 +812,6 @@ sub chart_distro { return join("\n", @results) . "\n"; } - -# Sub: distro_sparkline -# Make a sparkline of the graph. The following -# character codes are used: _.-^ If a bucket doesn't have a value, a -# space is used. So _ buckets are the lowest lines on the full graph -# (), and ^ are the peaks on the full graph. See -# QueryReportFormatter.t for several examples. -# -# This sub isn't the most optimized. The first half is the same code -# as . Then the latter code, unique to this sub, -# essentially compresses the full chart further into 8 characters using -# the 4 char codes above. -# -# Parameters: -# %args - Arguments -# -# Required Arguments: -# ea - object -# item - Item in results to chart -# attrib - Attribute of item to chart -# -# Returns: -# Sparkchart string -sub distro_sparkline { - my ( $self, %args ) = @_; - foreach my $arg ( qw(ea item attrib) ) { - die "I need a $arg argument" unless defined $args{$arg}; - } - my $ea = $args{ea}; - my $item = $args{item}; - my $attrib = $args{attrib}; - - my $results = $ea->results(); - my $store = $results->{classes}->{$item}->{$attrib}; - my $vals = $store->{all}; - - my $all_zeros_sparkline = " " x 8; - - return $all_zeros_sparkline unless defined $vals && scalar %$vals; - - my @buck_tens = $ea->buckets_of(10); - my @distro = map { 0 } (0 .. 7); - my @buckets = map { 0 } (0..999); - map { $buckets[$_] = $vals->{$_} } keys %$vals; - $vals = \@buckets; - map { $distro[$buck_tens[$_]] += $vals->[$_] } (1 .. @$vals - 1); - - my $vals_per_mark; - my $max_val = 0; - my $max_disp_width = 64; - foreach my $n_vals ( @distro ) { - $max_val = $n_vals if $n_vals > $max_val; - } - $vals_per_mark = $max_val / $max_disp_width; - - my ($min, $max); - foreach my $i ( 0 .. $#distro ) { - my $n_vals = $distro[$i]; - my $n_marks = $n_vals / ($vals_per_mark || 1); - $n_marks = 1 if $n_marks < 1 && $n_vals > 0; - - $min = $n_marks if $n_marks && (!$min || $n_marks < $min); - $max = $n_marks if !$max || $n_marks > $max; - } - return $all_zeros_sparkline unless $min && $max; - - # That ^ code is mostly the same as chart_distro(). Now here's - # our own unique code. - - # Divide the range by 4 because there are 4 char codes: _.-^ - $min = 0 if $min == $max; - my @range_min; - my $d = floor((($max+0.00001)-$min) / 4); - for my $x ( 1..4 ) { - push @range_min, $min + ($d * $x); - } - - my $sparkline = ""; - foreach my $i ( 0 .. $#distro ) { - my $n_vals = $distro[$i]; - my $n_marks = $n_vals / ($vals_per_mark || 1); - $n_marks = 1 if $n_marks < 1 && $n_vals > 0; - $sparkline .= $n_marks <= 0 ? ' ' - : $n_marks <= $range_min[0] ? '_' - : $n_marks <= $range_min[1] ? '.' - : $n_marks <= $range_min[2] ? '-' - : '^'; - } - - return $sparkline; -} - # Profile subreport (issue 381). # Arguments: # * ea obj: EventAggregator @@ -839,7 +820,6 @@ sub distro_sparkline { # Optional arguments: # * other arrayref: other items (that didn't make it into top worst) # * distill_args hashref: extra args for distill() -# * ReportFormatter obj: passed-in ReportFormatter for testing sub profile { my ( $self, %args ) = @_; foreach my $arg ( qw(ea worst groupby) ) { @@ -851,7 +831,6 @@ sub profile { my $groupby = $args{groupby}; my $qr = $self->{QueryRewriter}; - my $o = $self->{OptionParser}; # Total response time of all events. my $results = $ea->results(); @@ -874,41 +853,20 @@ sub profile { $qr->distill($samp_query, %{$args{distill_args}}) : $item, id => $groupby eq 'fingerprint' ? make_checksum($item) : '', vmr => ($query_time->{stddev}**2) / ($query_time->{avg} || 1), - apdex => defined $query_time->{apdex} ? $query_time->{apdex} : "NS", ); - # Get EXPLAIN sparkline if --explain. - if ( $o->get('explain') && $samp_query ) { - my ($default_db) = $sample->{db} ? $sample->{db} - : $stats->{db}->{unq} ? keys %{$stats->{db}->{unq}} - : undef; - eval { - $profile{explain_sparkline} = $self->explain_sparkline( - $samp_query, $default_db); - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d("Failed to get EXPLAIN sparkline:", $EVAL_ERROR); - } - } - push @profiles, \%profile; } - my $report = $self->{formatter_for}->{profile} || new ReportFormatter( - line_width => LINE_LENGTH, - long_last_column => 1, - extend_right => 1, - ); - $report->set_title('Profile'); + my $report = $self->ReportFormatter(); + $report->title('Profile'); my @cols = ( { name => 'Rank', right_justify => 1, }, { name => 'Query ID', }, { name => 'Response time', right_justify => 1, }, { name => 'Calls', right_justify => 1, }, { name => 'R/Call', right_justify => 1, }, - { name => 'Apdx', right_justify => 1, width => 4, }, { name => 'V/M', right_justify => 1, width => 5, }, - ( $o->get('explain') ? { name => 'EXPLAIN' } : () ), { name => 'Item', }, ); $report->set_columns(@cols); @@ -924,9 +882,7 @@ sub profile { "$rt $rtp", $item->{cnt}, $rc, - $item->{apdex}, $vmr, - ( $o->get('explain') ? $item->{explain_sparkline} || "" : () ), $item->{sample}, ); $report->add_line(@vals); @@ -954,9 +910,7 @@ sub profile { "$rt $rtp", $misc->{cnt}, $rc, - 'NS', # Apdex is not meaningful here '0.0', # variance-to-mean ratio is not meaningful here - ( $o->get('explain') ? "MISC" : () ), "<".scalar @$other." ITEMS>", ); } @@ -971,7 +925,6 @@ sub profile { # * groupby scalar: attrib worst items grouped by # Optional arguments: # * distill_args hashref: extra args for distill() -# * ReportFormatter obj: passed-in ReportFormatter for testing sub prepared { my ( $self, %args ) = @_; foreach my $arg ( qw(ea worst groupby) ) { @@ -1056,12 +1009,8 @@ sub prepared { # Return unless there are prepared statements to report. return unless scalar @prepared; - my $report = $self->{formatter_for}->{prepared} || new ReportFormatter( - line_width => LINE_LENGTH, - long_last_column => 1, - extend_right => 1, - ); - $report->set_title('Prepared statements'); + my $report = $self->ReportFormatter(); + $report->title('Prepared statements'); $report->set_columns( { name => 'Rank', right_justify => 1, }, { name => 'Query ID', }, @@ -1097,7 +1046,7 @@ sub make_global_header { # First line: # Attribute total min max avg 95% stddev median push @lines, - sprintf $self->{num_format}, "Attribute", '', @{$self->{global_headers}}; + sprintf $self->{num_format}, "Attribute", '', @{$self->global_headers()}; # Underline first line: # ========= ======= ======= ======= ======= ======= ======= ======= @@ -1105,7 +1054,7 @@ sub make_global_header { # Hard-coded values aren't ideal but this code rarely changes. push @lines, sprintf $self->{num_format}, - (map { "=" x $_ } $self->{label_width}), + (map { "=" x $_ } $self->label_width()), (map { " " x $_ } qw(3)), # no pct column in global header (map { "=" x $_ } qw(7 7 7 7 7 7 7)); @@ -1123,13 +1072,13 @@ sub make_event_header { my @lines; push @lines, - sprintf $self->{num_format}, "Attribute", @{$self->{event_headers}}; + sprintf $self->{num_format}, "Attribute", @{$self->event_headers()}; # The numbers 6, 7, 7, etc. are the field widths from make_header(). # Hard-coded values aren't ideal but this code rarely changes. push @lines, sprintf $self->{num_format}, - map { "=" x $_ } ($self->{label_width}, qw(3 7 7 7 7 7 7 7)); + map { "=" x $_ } ($self->label_width(), qw(3 7 7 7 7 7 7 7)); # End result should be like: # Attribute pct total min max avg 95% stddev median @@ -1148,7 +1097,7 @@ sub make_label { if ( $val =~ m/^InnoDB/ ) { $val =~ s/^InnoDB //; $val = $val eq 'trx id' ? "InnoDB trxID" - : substr($val, 0, $self->{label_width}); + : substr($val, 0, $self->label_width()); } $val = $val eq 'user' ? 'Users' @@ -1159,7 +1108,7 @@ sub make_label { : $val eq 'bytes' ? 'Query size' : $val eq 'Tmp disk tables' ? 'Tmp disk tbl' : $val eq 'Tmp table sizes' ? 'Tmp tbl size' - : substr($val, 0, $self->{label_width}); + : substr($val, 0, $self->label_width); return $val; } @@ -1177,8 +1126,7 @@ sub bool_percents { # Does pretty-printing for lists of strings like users, hosts, db. sub format_string_list { my ( $self, $attrib, $vals, $class_cnt ) = @_; - my $o = $self->{OptionParser}; - my $show_all = $o->get('show-all'); + my $show_all = $self->{options}->{show_all}; # Only class result values have unq. So if unq doesn't exist, # then we've been given global values. @@ -1318,7 +1266,7 @@ sub pref_sort { sub tables_report { my ( $self, @tables ) = @_; return '' unless @tables; - my $q = $self->{Quoter}; + my $q = $self->Quoter(); my $tables = ""; foreach my $db_tbl ( @tables ) { my ( $db, $tbl ) = @$db_tbl; @@ -1337,7 +1285,7 @@ sub explain_report { return '' unless $query; my $dbh = $self->{dbh}; - my $q = $self->{Quoter}; + my $q = $self->Quoter(); my $qp = $self->{QueryParser}; return '' unless $dbh && $q && $qp; @@ -1387,34 +1335,6 @@ sub format_time_range { return $min && $max ? "$min to $max" : ''; } -sub explain_sparkline { - my ( $self, $query, $db ) = @_; - return unless $query; - - my $q = $self->{Quoter}; - my $dbh = $self->{dbh}; - my $ex = $self->{ExplainAnalyzer}; - return unless $dbh && $ex; - - if ( $db ) { - PTDEBUG && _d($dbh, "USE", $db); - $dbh->do("USE " . $q->quote($db)); - } - my $res = $ex->normalize( - $ex->explain_query( - dbh => $dbh, - query => $query, - ) - ); - - my $sparkline; - if ( $res ) { - $sparkline = $ex->sparkline(explain => $res); - } - - return $sparkline; -} - sub _d { my ($package, undef, $line) = caller 0; @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } @@ -1423,6 +1343,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } +no Lmo; 1; } # ########################################################################### diff --git a/lib/QueryReview.pm b/lib/QueryReview.pm index aad98d8d..f2ecc062 100644 --- a/lib/QueryReview.pm +++ b/lib/QueryReview.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2011 Percona Inc. +# This program is copyright 2008-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -111,7 +111,7 @@ sub new { # table. sub set_history_options { my ( $self, %args ) = @_; - foreach my $arg ( qw(table dbh tbl_struct col_pat) ) { + foreach my $arg ( qw(table tbl_struct col_pat) ) { die "I need a $arg argument" unless $args{$arg}; } @@ -157,7 +157,7 @@ sub set_history_options { } @cols) . ')'; PTDEBUG && _d($sql); - $self->{history_sth} = $args{dbh}->prepare($sql); + $self->{history_sth} = $self->{dbh}->prepare($sql); $self->{history_metrics} = \@metrics; return; diff --git a/lib/QueryRewriter.pm b/lib/QueryRewriter.pm index 43d426e9..fddee79f 100644 --- a/lib/QueryRewriter.pm +++ b/lib/QueryRewriter.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Quoter.pm b/lib/Quoter.pm index ea05d00d..21359bd8 100644 --- a/lib/Quoter.pm +++ b/lib/Quoter.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/RawLogParser.pm b/lib/RawLogParser.pm index 1bd6426a..6052e98a 100644 --- a/lib/RawLogParser.pm +++ b/lib/RawLogParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2012 Percona Inc. +# This program is copyright 2012 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/ReadKeyMini.pm b/lib/ReadKeyMini.pm index 6bc620ed..601ad419 100644 --- a/lib/ReadKeyMini.pm +++ b/lib/ReadKeyMini.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2012 Percona Inc. +# This program is copyright 2010-2012 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/ReplicaLagWaiter.pm b/lib/ReplicaLagWaiter.pm index abe442f2..194406e0 100644 --- a/lib/ReplicaLagWaiter.pm +++ b/lib/ReplicaLagWaiter.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/ReportFormatter.pm b/lib/ReportFormatter.pm index 9b85f6b5..db8899ff 100644 --- a/lib/ReportFormatter.pm +++ b/lib/ReportFormatter.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -56,8 +56,7 @@ # calculated widths. package ReportFormatter; -use strict; -use warnings FATAL => 'all'; +use Lmo; use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -67,7 +66,6 @@ use POSIX qw(ceil); eval { require Term::ReadKey }; my $have_term = $EVAL_ERROR ? 0 : 1; -# Arguments: # * underline_header bool: underline headers with = # * line_prefix scalar: prefix every line with this string # * line_width scalar: line width in characters or 'auto' @@ -77,42 +75,106 @@ my $have_term = $EVAL_ERROR ? 0 : 1; # * column_errors scalar: die or warn on column errors (default warn) # * truncate_header_side scalar: left or right (default left) # * strip_whitespace bool: strip leading and trailing whitespace -sub new { - my ( $class, %args ) = @_; - my @required_args = qw(); - foreach my $arg ( @required_args ) { - die "I need a $arg argument" unless $args{$arg}; - } - my $self = { - underline_header => 1, - line_prefix => '# ', - line_width => 78, - column_spacing => ' ', - extend_right => 0, - truncate_line_mark => '...', - column_errors => 'warn', - truncate_header_side => 'left', - strip_whitespace => 1, - %args, # args above can be overriden, args below cannot - n_cols => 0, - }; +# * title scalar: title for the report + +has underline_header => ( + is => 'ro', + isa => 'Bool', + default => sub { 1 }, +); +has line_prefix => ( + is => 'ro', + isa => 'Str', + default => sub { '# ' }, +); +has line_width => ( + is => 'ro', + isa => 'Int', + default => sub { 78 }, +); +has column_spacing => ( + is => 'ro', + isa => 'Str', + default => sub { ' ' }, +); +has extend_right => ( + is => 'ro', + isa => 'Bool', + default => sub { '' }, +); +has truncate_line_mark => ( + is => 'ro', + isa => 'Str', + default => sub { '...' }, +); +has column_errors => ( + is => 'ro', + isa => 'Str', + default => sub { 'warn' }, +); +has truncate_header_side => ( + is => 'ro', + isa => 'Str', + default => sub { 'left' }, +); +has strip_whitespace => ( + is => 'ro', + isa => 'Bool', + default => sub { 1 }, +); +has title => ( + is => 'rw', + isa => 'Str', + predicate => 'has_title', +); + +# Internal + +has n_cols => ( + is => 'rw', + isa => 'Int', + default => sub { 0 }, + init_arg => undef, +); + +has cols => ( + is => 'ro', + isa => 'ArrayRef', + init_arg => undef, + default => sub { [] }, + clearer => 'clear_cols', +); + +has lines => ( + is => 'ro', + isa => 'ArrayRef', + init_arg => undef, + default => sub { [] }, + clearer => 'clear_lines', +); + +has truncate_headers => ( + is => 'rw', + isa => 'Bool', + default => sub { undef }, + init_arg => undef, + clearer => 'clear_truncate_headers', +); + +sub BUILDARGS { + my $class = shift; + my $args = $class->SUPER::BUILDARGS(@_); # This is not tested or currently used, but I like the idea and - # think one day it will be very handy in mk-config-diff. - if ( ($self->{line_width} || '') eq 'auto' ) { + # think one day it will be very handy in pt-config-diff. + if ( ($args->{line_width} || '') eq 'auto' ) { die "Cannot auto-detect line width because the Term::ReadKey module " . "is not installed" unless $have_term; - ($self->{line_width}) = GetTerminalSize(); + ($args->{line_width}) = GetTerminalSize(); + PTDEBUG && _d('Line width:', $args->{line_width}); } - PTDEBUG && _d('Line width:', $self->{line_width}); - return bless $self, $class; -} - -sub set_title { - my ( $self, $title ) = @_; - $self->{title} = $title; - return; + return $args; } # @cols is an array of hashrefs. Each hashref describes a column and can @@ -139,7 +201,7 @@ sub set_columns { die "Column does not have a name" unless defined $col_name; if ( $col->{width} ) { - $col->{width_pct} = ceil(($col->{width} * 100) / $self->{line_width}); + $col->{width_pct} = ceil(($col->{width} * 100) / $self->line_width()); PTDEBUG && _d('col:', $col_name, 'width:', $col->{width}, 'chars =', $col->{width_pct}, '%'); } @@ -172,10 +234,10 @@ sub set_columns { # Used with extend_right. $col->{right_most} = 1 if $i == $#cols; - push @{$self->{cols}}, $col; + push @{$self->cols}, $col; } - $self->{n_cols} = scalar @cols; + $self->n_cols( scalar @cols ); if ( ($used_width || 0) > 100 ) { die "Total width_pct for all columns is >100%"; @@ -186,16 +248,16 @@ sub set_columns { my $wid_per_col = int((100 - $used_width) / scalar @auto_width_cols); PTDEBUG && _d('Line width left:', (100-$used_width), '%;', 'each auto width col:', $wid_per_col, '%'); - map { $self->{cols}->[$_]->{width_pct} = $wid_per_col } @auto_width_cols; + map { $self->cols->[$_]->{width_pct} = $wid_per_col } @auto_width_cols; } # Add to the minimum possible header width the spacing between columns. - $min_hdr_wid += ($self->{n_cols} - 1) * length $self->{column_spacing}; + $min_hdr_wid += ($self->n_cols() - 1) * length $self->column_spacing(); PTDEBUG && _d('min header width:', $min_hdr_wid); - if ( $min_hdr_wid > $self->{line_width} ) { + if ( $min_hdr_wid > $self->line_width() ) { PTDEBUG && _d('Will truncate headers because min header width', - $min_hdr_wid, '> line width', $self->{line_width}); - $self->{truncate_headers} = 1; + $min_hdr_wid, '> line width', $self->line_width()); + $self->truncate_headers(1); } return; @@ -207,14 +269,14 @@ sub set_columns { sub add_line { my ( $self, @vals ) = @_; my $n_vals = scalar @vals; - if ( $n_vals != $self->{n_cols} ) { + if ( $n_vals != $self->n_cols() ) { $self->_column_error("Number of values $n_vals does not match " - . "number of columns $self->{n_cols}"); + . "number of columns " . $self->n_cols()); } for my $i ( 0..($n_vals-1) ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $val = defined $vals[$i] ? $vals[$i] : $col->{undef_value}; - if ( $self->{strip_whitespace} ) { + if ( $self->strip_whitespace() ) { $val =~ s/^\s+//g; $val =~ s/\s+$//; $vals[$i] = $val; @@ -223,7 +285,7 @@ sub add_line { $col->{min_val} = min($width, ($col->{min_val} || $width)); $col->{max_val} = max($width, ($col->{max_val} || $width)); } - push @{$self->{lines}}, \@vals; + push @{$self->lines}, \@vals; return; } @@ -232,12 +294,14 @@ sub get_report { my ( $self, %args ) = @_; $self->_calculate_column_widths(); - $self->_truncate_headers() if $self->{truncate_headers}; + if ( $self->truncate_headers() ) { + $self->_truncate_headers(); + } $self->_truncate_line_values(%args); my @col_fmts = $self->_make_column_formats(); - my $fmt = ($self->{line_prefix} || '') - . join($self->{column_spacing}, @col_fmts); + my $fmt = $self->line_prefix() + . join($self->column_spacing(), @col_fmts); PTDEBUG && _d('Format:', $fmt); # Make the printf line format for the header and ensure that its labels @@ -246,15 +310,15 @@ sub get_report { # Build the report line by line, starting with the title and header lines. my @lines; - push @lines, sprintf "$self->{line_prefix}$self->{title}" if $self->{title}; + push @lines, $self->line_prefix() . $self->title() if $self->has_title(); push @lines, $self->_truncate_line( - sprintf($hdr_fmt, map { $_->{name} } @{$self->{cols}}), + sprintf($hdr_fmt, map { $_->{name} } @{$self->cols}), strip => 1, mark => '', ); - if ( $self->{underline_header} ) { - my @underlines = map { '=' x $_->{print_width} } @{$self->{cols}}; + if ( $self->underline_header() ) { + my @underlines = map { '=' x $_->{print_width} } @{$self->cols}; push @lines, $self->_truncate_line( sprintf($fmt, map { $_ || '' } @underlines), mark => '', @@ -265,19 +329,24 @@ sub get_report { my $vals = $_; my $i = 0; my @vals = map { - my $val = defined $_ ? $_ : $self->{cols}->[$i++]->{undef_value}; + my $val = defined $_ ? $_ : $self->cols->[$i++]->{undef_value}; $val = '' if !defined $val; $val =~ s/\n/ /g; $val; } @$vals; my $line = sprintf($fmt, @vals); - if ( $self->{extend_right} ) { + if ( $self->extend_right() ) { $line; } else { $self->_truncate_line($line); } - } @{$self->{lines}}; + } @{$self->lines}; + + # Clean up any leftover state + $self->clear_cols(); + $self->clear_lines(); + $self->clear_truncate_headers(); return join("\n", @lines) . "\n"; } @@ -285,7 +354,7 @@ sub get_report { sub truncate_value { my ( $self, $col, $val, $width, $side ) = @_; return $val if length $val <= $width; - return $val if $col->{right_most} && $self->{extend_right}; + return $val if $col->{right_most} && $self->extend_right(); $side ||= $col->{truncate_side}; my $mark = $col->{truncate_mark}; if ( $side eq 'right' ) { @@ -305,8 +374,8 @@ sub _calculate_column_widths { my ( $self ) = @_; my $extra_space = 0; - foreach my $col ( @{$self->{cols}} ) { - my $print_width = int($self->{line_width} * ($col->{width_pct} / 100)); + foreach my $col ( @{$self->cols} ) { + my $print_width = int($self->line_width() * ($col->{width_pct} / 100)); PTDEBUG && _d('col:', $col->{name}, 'width pct:', $col->{width_pct}, 'char width:', $print_width, @@ -330,7 +399,7 @@ sub _calculate_column_widths { PTDEBUG && _d('Extra space:', $extra_space); while ( $extra_space-- ) { - foreach my $col ( @{$self->{cols}} ) { + foreach my $col ( @{$self->cols} ) { if ( $col->{auto_width} && ( $col->{print_width} < $col->{max_val} || $col->{print_width} < $col->{header_width}) @@ -346,8 +415,8 @@ sub _calculate_column_widths { sub _truncate_headers { my ( $self, $col ) = @_; - my $side = $self->{truncate_header_side}; - foreach my $col ( @{$self->{cols}} ) { + my $side = $self->truncate_header_side(); + foreach my $col ( @{$self->cols} ) { my $col_name = $col->{name}; my $print_width = $col->{print_width}; next if length $col_name <= $print_width; @@ -360,10 +429,10 @@ sub _truncate_headers { sub _truncate_line_values { my ( $self, %args ) = @_; - my $n_vals = $self->{n_cols} - 1; - foreach my $vals ( @{$self->{lines}} ) { + my $n_vals = $self->n_cols() - 1; + foreach my $vals ( @{$self->lines} ) { for my $i ( 0..$n_vals ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; my $val = defined $vals->[$i] ? $vals->[$i] : $col->{undef_value}; my $width = length $val; @@ -393,9 +462,9 @@ sub _truncate_line_values { sub _make_column_formats { my ( $self ) = @_; my @col_fmts; - my $n_cols = $self->{n_cols} - 1; + my $n_cols = $self->n_cols() - 1; for my $i ( 0..$n_cols ) { - my $col = $self->{cols}->[$i]; + my $col = $self->cols->[$i]; # Normally right-most col has no width so it can potentially # extend_right. But if it's right-justified, it requires a width. @@ -410,12 +479,12 @@ sub _make_column_formats { sub _truncate_line { my ( $self, $line, %args ) = @_; - my $mark = defined $args{mark} ? $args{mark} : $self->{truncate_line_mark}; + my $mark = defined $args{mark} ? $args{mark} : $self->truncate_line_mark(); if ( $line ) { $line =~ s/\s+$// if $args{strip}; my $len = length($line); - if ( $len > $self->{line_width} ) { - $line = substr($line, 0, $self->{line_width} - length $mark); + if ( $len > $self->line_width() ) { + $line = substr($line, 0, $self->line_width() - length $mark); $line .= $mark if $mark; } } @@ -425,7 +494,7 @@ sub _truncate_line { sub _column_error { my ( $self, $err ) = @_; my $msg = "Column error: $err"; - $self->{column_errors} eq 'die' ? die $msg : warn $msg; + $self->column_errors() eq 'die' ? die $msg : warn $msg; return; } @@ -437,6 +506,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } +no Lmo; 1; } # ########################################################################### diff --git a/lib/Retry.pm b/lib/Retry.pm index ca8d9366..43a8f840 100644 --- a/lib/Retry.pm +++ b/lib/Retry.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/RowChecksum.pm b/lib/RowChecksum.pm index 8c58b6fb..c567c19b 100644 --- a/lib/RowChecksum.pm +++ b/lib/RowChecksum.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/RowDiff.pm b/lib/RowDiff.pm index 7f254ad6..80e33b99 100644 --- a/lib/RowDiff.pm +++ b/lib/RowDiff.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Runtime.pm b/lib/Runtime.pm index 6ba0bef9..18e266a8 100644 --- a/lib/Runtime.pm +++ b/lib/Runtime.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/SQLParser.pm b/lib/SQLParser.pm index d3980806..ba9b69e3 100644 --- a/lib/SQLParser.pm +++ b/lib/SQLParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2012 Percona Inc. +# This program is copyright 2010-2012 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Sandbox.pm b/lib/Sandbox.pm index e42ad3ce..0a574648 100644 --- a/lib/Sandbox.pm +++ b/lib/Sandbox.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2012 Percona Inc. +# This program is copyright 2008-2012 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Schema.pm b/lib/Schema.pm index 77f8c980..5d8b7ff0 100644 --- a/lib/Schema.pm +++ b/lib/Schema.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/SchemaIterator.pm b/lib/SchemaIterator.pm index 56d46cd6..901ce76f 100644 --- a/lib/SchemaIterator.pm +++ b/lib/SchemaIterator.pm @@ -1,4 +1,4 @@ -# This program is copyright 2009-2011 Percona Inc. +# This program is copyright 2009-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/SimpleTCPDumpParser.pm b/lib/SimpleTCPDumpParser.pm index ca68848c..b462b9a5 100644 --- a/lib/SimpleTCPDumpParser.pm +++ b/lib/SimpleTCPDumpParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/SlowLogParser.pm b/lib/SlowLogParser.pm index 9840539c..d1fc1b16 100644 --- a/lib/SlowLogParser.pm +++ b/lib/SlowLogParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/SlowLogWriter.pm b/lib/SlowLogWriter.pm index fb209fa2..84ed0867 100644 --- a/lib/SlowLogWriter.pm +++ b/lib/SlowLogWriter.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/SysLogParser.pm b/lib/SysLogParser.pm index e094705b..ae36f39c 100644 --- a/lib/SysLogParser.pm +++ b/lib/SysLogParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2010-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TCPRequestAggregator.pm b/lib/TCPRequestAggregator.pm index 1be73f94..0655f02f 100644 --- a/lib/TCPRequestAggregator.pm +++ b/lib/TCPRequestAggregator.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TableChecksum.pm b/lib/TableChecksum.pm index 2b7206c0..59c8a489 100644 --- a/lib/TableChecksum.pm +++ b/lib/TableChecksum.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TableChunker.pm b/lib/TableChunker.pm index 03235b45..1130a61b 100644 --- a/lib/TableChunker.pm +++ b/lib/TableChunker.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TableNibbler.pm b/lib/TableNibbler.pm index 788598ca..0eed5177 100644 --- a/lib/TableNibbler.pm +++ b/lib/TableNibbler.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TableParser.pm b/lib/TableParser.pm index 91a71840..9bc53303 100644 --- a/lib/TableParser.pm +++ b/lib/TableParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -302,7 +302,7 @@ sub check_table { die "I need a $arg argument" unless $args{$arg}; } my ($dbh, $db, $tbl) = @args{@required_args}; - my $q = $self->{Quoter}; + my $q = $self->{Quoter} || 'Quoter'; my $db_tbl = $q->quote($db, $tbl); PTDEBUG && _d('Checking', $db_tbl); diff --git a/lib/TableSyncChunk.pm b/lib/TableSyncChunk.pm index 65aea35e..610ccba9 100644 --- a/lib/TableSyncChunk.pm +++ b/lib/TableSyncChunk.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TableSyncGroupBy.pm b/lib/TableSyncGroupBy.pm index 7115d632..2e2d2088 100644 --- a/lib/TableSyncGroupBy.pm +++ b/lib/TableSyncGroupBy.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TableSyncNibble.pm b/lib/TableSyncNibble.pm index 8fe07af9..62b637a1 100644 --- a/lib/TableSyncNibble.pm +++ b/lib/TableSyncNibble.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TableSyncStream.pm b/lib/TableSyncStream.pm index 541f2bac..0d30c57e 100644 --- a/lib/TableSyncStream.pm +++ b/lib/TableSyncStream.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TableSyncer.pm b/lib/TableSyncer.pm index f096103e..9901397d 100644 --- a/lib/TableSyncer.pm +++ b/lib/TableSyncer.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TableUsage.pm b/lib/TableUsage.pm index acc349bb..bf6ea442 100644 --- a/lib/TableUsage.pm +++ b/lib/TableUsage.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011-2012 Percona Inc. +# This program is copyright 2011-2012 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TcpdumpParser.pm b/lib/TcpdumpParser.pm index 79379925..930e2077 100644 --- a/lib/TcpdumpParser.pm +++ b/lib/TcpdumpParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/TextResultSetParser.pm b/lib/TextResultSetParser.pm index fafd618a..0de3b2f9 100644 --- a/lib/TextResultSetParser.pm +++ b/lib/TextResultSetParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2011 Percona Inc. +# This program is copyright 2008-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/Transformers.pm b/lib/Transformers.pm index 00bd89f6..f378c474 100644 --- a/lib/Transformers.pm +++ b/lib/Transformers.pm @@ -1,4 +1,4 @@ -# This program is copyright 2008-2011 Percona Inc. +# This program is copyright 2008-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -31,24 +31,26 @@ use Time::Local qw(timegm timelocal); use Digest::MD5 qw(md5_hex); use B qw(); -require Exporter; -our @ISA = qw(Exporter); -our %EXPORT_TAGS = (); -our @EXPORT = (); -our @EXPORT_OK = qw( - micro_t - percentage_of - secs_to_time - time_to_secs - shorten - ts - parse_timestamp - unix_timestamp - any_unix_timestamp - make_checksum - crc32 - encode_json -); +BEGIN { + require Exporter; + our @ISA = qw(Exporter); + our %EXPORT_TAGS = (); + our @EXPORT = (); + our @EXPORT_OK = qw( + micro_t + percentage_of + secs_to_time + time_to_secs + shorten + ts + parse_timestamp + unix_timestamp + any_unix_timestamp + make_checksum + crc32 + encode_json + ); +} our $mysql_ts = qr/(\d\d)(\d\d)(\d\d) +(\d+):(\d+):(\d+)(\.\d+)?/; our $proper_ts = qr/(\d\d\d\d)-(\d\d)-(\d\d)[T ](\d\d):(\d\d):(\d\d)(\.\d+)?/; diff --git a/lib/VariableAdvisorRules.pm b/lib/VariableAdvisorRules.pm index 16a1af05..7a9d3091 100644 --- a/lib/VariableAdvisorRules.pm +++ b/lib/VariableAdvisorRules.pm @@ -1,4 +1,4 @@ -# This program is copyright 2010-2011 Percona Inc. +# This program is copyright 2010-2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/VersionCheck.pm b/lib/VersionCheck.pm deleted file mode 100644 index 95b19e15..00000000 --- a/lib/VersionCheck.pm +++ /dev/null @@ -1,312 +0,0 @@ -# This program is copyright 2012 Percona Inc. -# Feedback and improvements are welcome. -# -# THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED -# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF -# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. -# -# This program is free software; you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free Software -# Foundation, version 2; OR the Perl Artistic License. On UNIX and similar -# systems, you can issue `man perlgpl' or `man perlartistic' to read these -# licenses. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 59 Temple -# Place, Suite 330, Boston, MA 02111-1307 USA. -# ########################################################################### -# VersionCheck package -# ########################################################################### -{ -# Package: VersionCheck -# VersionCheck checks program versions with Percona. -package VersionCheck; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); - -use constant PTDEBUG => $ENV{PTDEBUG} || 0; - -use File::Basename (); -use Data::Dumper (); - -sub Dumper { - local $Data::Dumper::Indent = 1; - local $Data::Dumper::Sortkeys = 1; - local $Data::Dumper::Quotekeys = 0; - - Data::Dumper::Dumper(@_); -} - -sub new { - my ($class, %args) = @_; - my $self = { - valid_types => qr/ - ^(?: - os_version - |perl_version - |perl_module_version - |mysql_variable - |bin_version - )$/x, - }; - return bless $self, $class; -} - -sub parse_server_response { - my ($self, %args) = @_; - my @required_args = qw(response); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($response) = @args{@required_args}; - - my %items = map { - my ($item, $type, $vars) = split(";", $_); - if ( !defined $args{split_vars} || $args{split_vars} ) { - $vars = [ split(",", ($vars || '')) ]; - } - $item => { - item => $item, - type => $type, - vars => $vars, - }; - } split("\n", $response); - - PTDEBUG && _d('Items:', Dumper(\%items)); - - return \%items; -} - -sub get_versions { - my ($self, %args) = @_; - my @required_args = qw(items); - foreach my $arg ( @required_args ) { - die "I need a $arg arugment" unless $args{$arg}; - } - my ($items) = @args{@required_args}; - - my %versions; - foreach my $item ( values %$items ) { - next unless $self->valid_item($item); - - eval { - my $func = 'get_' . $item->{type}; - my $version = $self->$func( - item => $item, - instances => $args{instances}, - ); - if ( $version ) { - chomp $version unless ref($version); - $versions{$item->{item}} = $version; - } - }; - if ( $EVAL_ERROR ) { - PTDEBUG && _d('Error getting version for', Dumper($item), $EVAL_ERROR); - } - } - - return \%versions; -} - -sub valid_item { - my ($self, $item) = @_; - return unless $item; - - if ( ($item->{type} || '') !~ m/$self->{valid_types}/ ) { - PTDEBUG && _d('Invalid type:', $item->{type}); - return; - } - - return 1; -} - -sub get_os_version { - my ($self) = @_; - - if ( $OSNAME eq 'MSWin32' ) { - require Win32; - return Win32::GetOSDisplayName(); - } - - chomp(my $platform = `uname -s`); - PTDEBUG && _d('platform:', $platform); - return $OSNAME unless $platform; - - chomp(my $lsb_release - = `which lsb_release 2>/dev/null | awk '{print \$1}'` || ''); - PTDEBUG && _d('lsb_release:', $lsb_release); - - my $release = ""; - - if ( $platform eq 'Linux' ) { - if ( -f "/etc/fedora-release" ) { - $release = `cat /etc/fedora-release`; - } - elsif ( -f "/etc/redhat-release" ) { - $release = `cat /etc/redhat-release`; - } - elsif ( -f "/etc/system-release" ) { - $release = `cat /etc/system-release`; - } - elsif ( $lsb_release ) { - $release = `$lsb_release -ds`; - } - elsif ( -f "/etc/lsb-release" ) { - $release = `grep DISTRIB_DESCRIPTION /etc/lsb-release`; - $release =~ s/^\w+="([^"]+)".+/$1/; - } - elsif ( -f "/etc/debian_version" ) { - chomp(my $rel = `cat /etc/debian_version`); - $release = "Debian $rel"; - if ( -f "/etc/apt/sources.list" ) { - chomp(my $code_name = `awk '/^deb/ {print \$3}' /etc/apt/sources.list | awk -F/ '{print \$1}'| awk 'BEGIN {FS="|"} {print \$1}' | sort | uniq -c | sort -rn | head -n1 | awk '{print \$2}'`); - $release .= " ($code_name)" if $code_name; - } - } - elsif ( -f "/etc/os-release" ) { # openSUSE - chomp($release = `grep PRETTY_NAME /etc/os-release`); - $release =~ s/^PRETTY_NAME="(.+)"$/$1/; - } - elsif ( `ls /etc/*release 2>/dev/null` ) { - if ( `grep DISTRIB_DESCRIPTION /etc/*release 2>/dev/null` ) { - $release = `grep DISTRIB_DESCRIPTION /etc/*release | head -n1`; - } - else { - $release = `cat /etc/*release | head -n1`; - } - } - } - elsif ( $platform =~ m/(?:BSD|^Darwin)$/ ) { - my $rel = `uname -r`; - $release = "$platform $rel"; - } - elsif ( $platform eq "SunOS" ) { - my $rel = `head -n1 /etc/release` || `uname -r`; - $release = "$platform $rel"; - } - - if ( !$release ) { - PTDEBUG && _d('Failed to get the release, using platform'); - $release = $platform; - } - chomp($release); - - # For Gentoo, which returns a value in quotes - $release =~ s/^"|"$//g; - - PTDEBUG && _d('OS version =', $release); - return $release; -} - -sub get_perl_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - my $version = sprintf '%vd', $PERL_VERSION; - PTDEBUG && _d('Perl version', $version); - return $version; -} - -sub get_perl_module_version { - my ($self, %args) = @_; - my $item = $args{item}; - return unless $item; - - # If there's a var, then its an explicit Perl variable name to get, - # else the item name is an implicity Perl module name to which we - # append ::VERSION to get the module's version. - my $var = $item->{item} . '::VERSION'; - my $version = _get_scalar($var); - PTDEBUG && _d('Perl version for', $var, '=', "$version"); - - # Explicitly stringify this else $PERL_VERSION will return - # as a version object. - return $version ? "$version" : $version; -} - -sub _get_scalar { - no strict; - return ${*{shift()}}; -} - -sub get_mysql_variable { - my $self = shift; - return $self->_get_from_mysql( - show => 'VARIABLES', - @_, - ); -} - -sub _get_from_mysql { - my ($self, %args) = @_; - my $show = $args{show}; - my $item = $args{item}; - my $instances = $args{instances}; - return unless $show && $item; - - if ( !$instances || !@$instances ) { - if ( $ENV{PTVCDEBUG} || PTDEBUG ) { - _d('Cannot check', $item, 'because there are no MySQL instances'); - } - return; - } - - my @versions; - my %version_for; - foreach my $instance ( @$instances ) { - my $dbh = $instance->{dbh}; - local $dbh->{FetchHashKeyName} = 'NAME_lc'; - my $sql = qq/SHOW $show/; - PTDEBUG && _d($sql); - my $rows = $dbh->selectall_hashref($sql, 'variable_name'); - - my @versions; - foreach my $var ( @{$item->{vars}} ) { - $var = lc($var); - my $version = $rows->{$var}->{value}; - PTDEBUG && _d('MySQL version for', $item->{item}, '=', $version, - 'on', $instance->{name}); - push @versions, $version; - } - - $version_for{ $instance->{id} } = join(' ', @versions); - } - - return \%version_for; -} - -sub get_bin_version { - my ($self, %args) = @_; - my $item = $args{item}; - my $cmd = $item->{item}; - return unless $cmd; - - my $sanitized_command = File::Basename::basename($cmd); - PTDEBUG && _d('cmd:', $cmd, 'sanitized:', $sanitized_command); - return if $sanitized_command !~ /\A[a-zA-Z0-9_-]+\z/; - - my $output = `$sanitized_command --version 2>&1`; - PTDEBUG && _d('output:', $output); - - my ($version) = $output =~ /v?([0-9]+\.[0-9]+(?:\.[\w-]+)?)/; - - PTDEBUG && _d('Version for', $sanitized_command, '=', $version); - return $version; -} - -sub _d { - my ($package, undef, $line) = caller 0; - @_ = map { (my $temp = $_) =~ s/\n/\n# /g; $temp; } - map { defined $_ ? $_ : 'undef' } - @_; - print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; -} - -1; -} -# ########################################################################### -# End VersionCheck package -# ########################################################################### diff --git a/lib/VersionParser.pm b/lib/VersionParser.pm index 4dace928..cefc0e94 100644 --- a/lib/VersionParser.pm +++ b/lib/VersionParser.pm @@ -1,4 +1,4 @@ -# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Inc. +# This program is copyright 2007-2011 Baron Schwartz, 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED @@ -22,7 +22,7 @@ # VersionParser parses a MySQL version string. package VersionParser; -use Mo; +use Lmo; use Scalar::Util qw(blessed); use English qw(-no_match_vars); use constant PTDEBUG => $ENV{PTDEBUG} || 0; @@ -213,7 +213,7 @@ sub _d { print STDERR "# $package:$line $PID ", join(' ', @_), "\n"; } -no Mo; +no Lmo; 1; } # ########################################################################### diff --git a/lib/WeightedAvgRate.pm b/lib/WeightedAvgRate.pm index 9ced889b..0c46fcef 100644 --- a/lib/WeightedAvgRate.pm +++ b/lib/WeightedAvgRate.pm @@ -1,4 +1,4 @@ -# This program is copyright 2011 Percona Inc. +# This program is copyright 2011 Percona Ireland Ltd. # Feedback and improvements are welcome. # # THIS PROGRAM IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED diff --git a/lib/bash/log_warn_die.sh b/lib/bash/log_warn_die.sh index aa07e31e..541f7c3c 100644 --- a/lib/bash/log_warn_die.sh +++ b/lib/bash/log_warn_die.sh @@ -28,23 +28,32 @@ PTFUNCNAME="" PTDEBUG="${PTDEBUG:-""}" EXIT_STATUS=0 -log() { - TS=$(date +%F-%T | tr ':-' '_'); +ts() { + TS=$(date +%F-%T | tr ':-' '_') echo "$TS $*" } +info() { + [ ${OPT_VERBOSE:-3} -ge 3 ] && ts "$*" +} + +log() { + [ ${OPT_VERBOSE:-3} -ge 2 ] && ts "$*" +} + warn() { - log "$*" >&2 + [ ${OPT_VERBOSE:-3} -ge 1 ] && ts "$*" >&2 EXIT_STATUS=1 } die() { - warn "$*" + ts "$*" >&2 + EXIT_STATUS=1 exit 1 } _d () { - [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(log "$*")" >&2 + [ "$PTDEBUG" ] && echo "# $PTFUNCNAME: $(ts "$*")" >&2 } # ########################################################################### diff --git a/sandbox/jenkins-test b/sandbox/jenkins-test index fcd49277..086c2d4b 100755 --- a/sandbox/jenkins-test +++ b/sandbox/jenkins-test @@ -21,6 +21,9 @@ util/check-dev-env ######################### # Check the system env. # ######################### +env +df -h +w whoami id if [ "$(id -u)" = "0" ]; then diff --git a/sandbox/start-sandbox b/sandbox/start-sandbox index df668b1f..5b7e0179 100755 --- a/sandbox/start-sandbox +++ b/sandbox/start-sandbox @@ -27,6 +27,13 @@ debug_sandbox() { fi } +mysql_upgrade_on() { + local cnf_file="$1" + local upgrade="$(which mysql_upgrade)" + + $upgrade --defaults-file=$cnf_file --skip-write-binlog +} + make_sandbox() { # Make the sandbox dir and extract the base files. rm -rf /tmp/$port || die "Failed to rm /tmp/$port" @@ -138,6 +145,10 @@ make_sandbox() { /tmp/$port/use -e "CREATE TABLE IF NOT EXISTS percona_test.sentinel (id INT PRIMARY KEY, ping VARCHAR(64) NOT NULL DEFAULT '')"; /tmp/$port/use -e "REPLACE INTO percona_test.sentinel (id, ping) VALUES (1, '')"; + if [ -n "${MYSQL_UPGRADE:-""}" ]; then + mysql_upgrade_on /tmp/$port/my.sandbox.cnf + fi + # If the sandbox is a slave, start the slave. if [ "$type" = "slave" ]; then /tmp/$port/use -e "change master to master_host='127.0.0.1', master_user='msandbox', master_password='msandbox', master_port=$master_port" diff --git a/t/lib/EventAggregator.t b/t/lib/EventAggregator.t index 38a16ca2..7ee7e30a 100644 --- a/t/lib/EventAggregator.t +++ b/t/lib/EventAggregator.t @@ -9,7 +9,7 @@ BEGIN { use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); -use Test::More tests => 82; +use Test::More; use QueryRewriter; use EventAggregator; @@ -431,7 +431,7 @@ foreach my $event (@$events) { is_deeply( $ea->results, $result, 'user aggregation' ); is($ea->type_for('Query_time'), 'num', 'Query_time is numeric'); -$ea->calculate_statistical_metrics(apdex_t => 1); +$ea->calculate_statistical_metrics(); is_deeply( $ea->metrics( where => 'bob', @@ -446,8 +446,6 @@ is_deeply( median => '0.000682', stddev => 0, pct_95 => '0.000682', - apdex_t => 1, - apdex => '1.00', }, 'Got simple hash of metrics from metrics()', ); @@ -466,8 +464,6 @@ is_deeply( median => 0, stddev => 0, pct_95 => 0, - apdex_t => undef, - apdex => undef, }, 'It does not crash on metrics()', ); @@ -1816,59 +1812,6 @@ is_deeply( "Merge results" ); -# ############################################################################# -# Apdex -# ############################################################################# - -my $samples = { - 280 => 10, # 0.81623354758492 satisfy - 281 => 10, # 0.85704522496417 satisfy - 282 => 10, # 0.89989748621238 satisfy - 283 => 50, # 0.94489236052300 satisfy - 284 => 50, # 0.99213697854915 satisfy - 285 => 10, # 1.04174382747661 tolerate - 290 => 10, # 1.32955843985657 tolerate - 313 => 1, # 4.08377033290049 frustrated -}; -my $apdex = $ea->calculate_apdex( - t => 1, - samples => $samples, -); - -is( - $apdex, - '0.93', - "Apdex score" -); - -$samples = { - 0 => 150, -}; -$apdex = $ea->calculate_apdex( - t => 1, - samples => $samples, -); - -is( - $apdex, - '1.00', - "Apdex score 1.00" -); - -$samples = { - 400 => 150, -}; -$apdex = $ea->calculate_apdex( - t => 1, - samples => $samples, -); - -is( - $apdex, - '0.00', - "Apdex score 0.00" -); - # ############################################################################# # Special-case attribs called *_crc for mqd --variations. # ############################################################################# @@ -1953,4 +1896,5 @@ like( qr/Complete test coverage/, '_d() works' ); +done_testing; exit; diff --git a/t/lib/ExplainAnalyzer.t b/t/lib/ExplainAnalyzer.t index 32ccc67f..161362cf 100644 --- a/t/lib/ExplainAnalyzer.t +++ b/t/lib/ExplainAnalyzer.t @@ -425,149 +425,6 @@ is_deeply( ], 'Got saved usage for 0xdeadbeef'); -# ############################################################################# -# Issue 1141: Add "spark charts" to mk-query-digest profile -# ############################################################################# -is( - $exa->sparkline(explain => - [ - { id => 1, - select_type => 'PRIMARY', - table => 'foo', - type => 'eq_ref', - possible_keys => ['idx'], - key => ['idx'], - key_len => [10], - ref => [], - rows => 100, - Extra => { - 'Using index' => 1, - 'Using where' => 1, - }, - }, - ], - ), - "E", - "sparkline: basic 1 table eq_ref" -); - -is( - $exa->sparkline(explain => - [ - { id => 1, - select_type => 'PRIMARY', - table => 'foo', - type => 'eq_ref', - possible_keys => ['idx'], - key => ['idx'], - key_len => [10], - ref => [], - rows => 100, - Extra => { - 'Using index' => 1, - 'Using where' => 1, - 'Using filesort' => 1, - }, - }, - { id => 2, - select_type => 'PRIMARY', - table => 'bar', - type => 'ref', - possible_keys => ['idx'], - key => ['idx'], - key_len => [10], - ref => ['foo.col'], - rows => 100, - Extra => { - }, - }, - ], - ), - "F>Er", - "sparkline: 2 table with filesort at start" -); - -is( - $exa->sparkline(explain => - [ - { id => 1, - select_type => 'PRIMARY', - table => 'foo', - type => 'range', - possible_keys => ['idx'], - key => ['idx'], - key_len => [10], - ref => [], - rows => 100, - Extra => { - }, - }, - { id => 2, - select_type => 'PRIMARY', - table => 'bar', - type => 'ref', - possible_keys => ['idx'], - key => ['idx'], - key_len => [10], - ref => ['foo.col'], - rows => 100, - Extra => { - 'Using temporary' => 1, - 'Using filesort' => 1, - }, - }, - ], - ), - "nr>TF", - "sparkline: 2 table with temp and filesort at end" -); - -is( - $exa->sparkline(explain => - [ - { id => 1, - select_type => 'PRIMARY', - table => undef, - type => undef, - possible_keys => [], - key => [], - key_len => [], - ref => [], - rows => undef, - Extra => { - 'No tables used' => 1, - }, - }, - { id => 1, - select_type => 'UNION', - table => 'a', - type => 'index', - possible_keys => [], - key => ['PRIMARY'], - key_len => [2], - ref => [], - rows => 200, - Extra => { - 'Using index' => 1, - }, - }, - { id => undef, - select_type => 'UNION RESULT', - table => '', - type => 'ALL', - possible_keys => [], - key => [], - key_len => [], - ref => [], - rows => undef, - Extra => {}, - }, - ], - ), - "-Ia", - "sparkline: 3 tables, using index" -); - # ############################################################################# # Done. # ############################################################################# diff --git a/t/lib/Mo/Bar.pm b/t/lib/Lmo/Bar.pm similarity index 77% rename from t/lib/Mo/Bar.pm rename to t/lib/Lmo/Bar.pm index 1a4a2410..91b7cc7b 100644 --- a/t/lib/Mo/Bar.pm +++ b/t/lib/Lmo/Bar.pm @@ -1,4 +1,4 @@ package Bar; -use Mo; +use Lmo; extends 'Foo'; 1; diff --git a/t/lib/Mo/Boo.pm b/t/lib/Lmo/Boo.pm similarity index 76% rename from t/lib/Mo/Boo.pm rename to t/lib/Lmo/Boo.pm index b6a716ee..8096c926 100644 --- a/t/lib/Mo/Boo.pm +++ b/t/lib/Lmo/Boo.pm @@ -1,5 +1,5 @@ package Boo; -use Mo; +use Lmo; has 'buff'; diff --git a/t/lib/Mo/Foo.pm b/t/lib/Lmo/Foo.pm similarity index 77% rename from t/lib/Mo/Foo.pm rename to t/lib/Lmo/Foo.pm index 728da69d..d2c896c8 100644 --- a/t/lib/Mo/Foo.pm +++ b/t/lib/Lmo/Foo.pm @@ -1,5 +1,5 @@ package Foo; -use Mo; +use Lmo; has 'stuff'; diff --git a/t/lib/Mo/build.t b/t/lib/Lmo/build.t similarity index 78% rename from t/lib/Mo/build.t rename to t/lib/Lmo/build.t index 1aa70c0b..2cc201fc 100644 --- a/t/lib/Mo/build.t +++ b/t/lib/Lmo/build.t @@ -14,31 +14,31 @@ use Test::More; $main::count = 1; package Foo; -use Mo 'build'; +use Lmo 'build'; has 'foo' => (is => 'rw'); sub BUILD { my $self = shift; - ::is_deeply(\@_, [qw(stuff 1)], "Foo's BUILD doesn't get the class name"); + ::is_deeply([sort @_], [sort qw(stuff 1)], "Foo's BUILD doesn't get the class name"); $self->foo($main::count++); } package Bar; -use Mo; +use Lmo; extends 'Foo'; has 'bar' => (is => 'rw'); package Baz; -use Mo; +use Lmo; extends 'Bar'; has 'baz' => (is => 'rw'); sub BUILD { my $self = shift; - ::is_deeply(\@_, [qw(stuff 1)], "Baz's BUILD doesn't get the class name"); + ::is_deeply([sort @_], [sort qw(stuff 1)], "Baz's BUILD doesn't get the class name"); $self->baz($main::count++); } package Gorch; -use Mo; +use Lmo; extends 'Baz'; has 'gorch' => (is => 'rw'); diff --git a/t/lib/Mo/buildargs.t b/t/lib/Lmo/buildargs.t similarity index 93% rename from t/lib/Mo/buildargs.t rename to t/lib/Lmo/buildargs.t index 403bd55d..ddc660da 100644 --- a/t/lib/Mo/buildargs.t +++ b/t/lib/Lmo/buildargs.t @@ -15,13 +15,13 @@ $main::count = 0; { package Nothing; - use Mo; + use Lmo; has nothing_special => ( is => 'rw' ); } ok(Nothing->can("BUILDARGS"), "Every class automatically gets buildargs"); package Foo; -use Mo; +use Lmo; has 'foo' => (is => 'rw'); sub BUILDARGS { my $class = shift; @@ -30,12 +30,12 @@ sub BUILDARGS { } package Bar; -use Mo; +use Lmo; extends 'Foo'; has 'bar' => (is => 'rw'); package Baz; -use Mo; +use Lmo; extends 'Bar'; has 'baz' => (is => 'rw'); sub BUILDARGS { @@ -45,7 +45,7 @@ sub BUILDARGS { } package Gorch; -use Mo; +use Lmo; extends 'Baz'; has 'gorch' => (is => 'rw'); @@ -53,7 +53,7 @@ package main; $main::count = 0; my $g = Foo->new; -is $main::count, 1, "A class with no explicit parent inherits SUPER::BUILDARGS from Mo::Object"; +is $main::count, 1, "A class with no explicit parent inherits SUPER::BUILDARGS from Lmo::Object"; $main::count = 0; $g = Gorch->new; diff --git a/t/lib/Mo/coerce.t b/t/lib/Lmo/coerce.t similarity index 98% rename from t/lib/Mo/coerce.t rename to t/lib/Lmo/coerce.t index 8af02b08..5aa1234f 100644 --- a/t/lib/Mo/coerce.t +++ b/t/lib/Lmo/coerce.t @@ -12,7 +12,7 @@ use English qw(-no_match_vars); use Test::More; package Foo::coerce; -use Mo; +use Lmo; has 'stuff' => (coerce => sub { uc $_[0] }); diff --git a/t/lib/Mo/extends.t b/t/lib/Lmo/extends.t similarity index 91% rename from t/lib/Mo/extends.t rename to t/lib/Lmo/extends.t index 30eb8731..a46ff3df 100644 --- a/t/lib/Mo/extends.t +++ b/t/lib/Lmo/extends.t @@ -11,7 +11,7 @@ use warnings FATAL => 'all'; use English qw(-no_match_vars); use Test::More; -use lib "$ENV{PERCONA_TOOLKIT_BRANCH}/t/lib/Mo"; +use lib "$ENV{PERCONA_TOOLKIT_BRANCH}/t/lib/Lmo"; use Bar; my $b = Bar->new; diff --git a/t/lib/Mo/handles.t b/t/lib/Lmo/handles.t similarity index 93% rename from t/lib/Mo/handles.t rename to t/lib/Lmo/handles.t index 653c396f..af6e822a 100644 --- a/t/lib/Mo/handles.t +++ b/t/lib/Lmo/handles.t @@ -21,14 +21,14 @@ use Test::More; { package Foo; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); has 'bar' => (is => 'rw', default => sub { 10 }); sub baz { 42 } package Bar; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); has 'foo' => ( is => 'rw', @@ -99,13 +99,13 @@ is($bar->foo_bar, 20, '... correctly curried a single argument'); { package Engine; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); sub go { 'Engine::go' } sub stop { 'Engine::stop' } package Car; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); has 'engine' => ( is => 'rw', @@ -137,14 +137,14 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); { package Baz; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); sub foo { 'Baz::foo' } sub bar { 'Baz::bar' } sub boo { 'Baz::boo' } package Baz::Proxy1; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); has 'baz' => ( is => 'ro', @@ -154,7 +154,7 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); ); package Baz::Proxy2; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); has 'baz' => ( is => 'ro', @@ -164,7 +164,7 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); ); package Baz::Proxy3; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); has 'baz' => ( is => 'ro', @@ -228,14 +228,14 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); requires 'bar'; package Foo::Baz; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); sub foo { 'Foo::Baz::FOO' } sub bar { 'Foo::Baz::BAR' } sub baz { 'Foo::Baz::BAZ' } package Foo::Thing; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); has 'thing' => ( is => 'rw', @@ -244,7 +244,7 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); ); package Foo::OtherThing; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); use Moose::Util::TypeConstraints; has 'other_thing' => ( @@ -288,7 +288,7 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); { package Foo::Autoloaded; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); sub AUTOLOAD { my $self = shift; @@ -304,7 +304,7 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); } package Bar::Autoloaded; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); has 'foo' => ( is => 'rw', @@ -313,7 +313,7 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); ); package Baz::Autoloaded; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); has 'foo' => ( is => 'rw', @@ -322,7 +322,7 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); ); package Goorch::Autoloaded; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); eval { has 'foo' => ( @@ -447,7 +447,7 @@ is($car->stop, 'Engine::stop', '... got the right value from ->stop'); { package Delegator; - use Mo qw(is required handles default builder); + use Lmo qw(is required handles default builder); sub full { 1 } sub stub; diff --git a/t/lib/Mo/init_arg.t b/t/lib/Lmo/init_arg.t similarity index 95% rename from t/lib/Mo/init_arg.t rename to t/lib/Lmo/init_arg.t index b6fab8d4..2c136a0a 100644 --- a/t/lib/Mo/init_arg.t +++ b/t/lib/Lmo/init_arg.t @@ -15,7 +15,7 @@ use Test::More; { package Foo; - use Mo qw( is init_arg ); + use Lmo qw( is init_arg ); eval { has 'foo' => ( @@ -64,7 +64,7 @@ use Test::More; { package Foo2; - use Mo qw( is init_arg clearer default ); + use Lmo qw( is init_arg clearer default ); my $counter; eval { diff --git a/t/lib/Mo/is.t b/t/lib/Lmo/is.t similarity index 97% rename from t/lib/Mo/is.t rename to t/lib/Lmo/is.t index 84ea47d1..02f1a63c 100644 --- a/t/lib/Mo/is.t +++ b/t/lib/Lmo/is.t @@ -12,7 +12,7 @@ use English qw(-no_match_vars); use Test::More; package Foo::is; -use Mo qw(is); +use Lmo qw(is); has 'stuff' => (is => 'ro'); diff --git a/t/lib/Mo/isa.t b/t/lib/Lmo/isa.t similarity index 97% rename from t/lib/Mo/isa.t rename to t/lib/Lmo/isa.t index 426c2cb9..b52d67f9 100644 --- a/t/lib/Mo/isa.t +++ b/t/lib/Lmo/isa.t @@ -29,7 +29,7 @@ sub lives_ok (&;$) { } package Foo::isa; -use Mo qw(isa); +use Lmo qw(isa); my @types = qw(Bool Num Int Str ArrayRef CodeRef HashRef RegexpRef); my @refs = ([], sub { }, {}, qr( )); @@ -191,11 +191,11 @@ my $thisperl = $^X; if ($^O ne 'VMS') {$thisperl .= $Config{_exe} unless $thisperl =~ m/$Config{_exe}$/i;} -my $pm_test = "$PerconaTest::trunk/t/lib/Mo/isa_subtest.pm"; +my $pm_test = "$PerconaTest::trunk/t/lib/Lmo/isa_subtest.pm"; ok( scalar(IPC::Cmd::run(command => [$thisperl, $pm_test])), - "Mo types work with Scalar::Util::PP", + "Lmo types work with Scalar::Util::PP", ); done_testing; diff --git a/t/lib/Mo/isa_subtest.pm b/t/lib/Lmo/isa_subtest.pm similarity index 98% rename from t/lib/Mo/isa_subtest.pm rename to t/lib/Lmo/isa_subtest.pm index 4097f10b..4cdd29e3 100644 --- a/t/lib/Mo/isa_subtest.pm +++ b/t/lib/Lmo/isa_subtest.pm @@ -16,7 +16,7 @@ use warnings; { package isa_subtest; - use Mo; + use Lmo; has attr => ( is => 'rw', diff --git a/t/lib/Lmo/meta.t b/t/lib/Lmo/meta.t new file mode 100644 index 00000000..40106511 --- /dev/null +++ b/t/lib/Lmo/meta.t @@ -0,0 +1,83 @@ +#!/usr/bin/perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +sub throws_ok (&;$) { + my ( $code, $pat, $msg ) = @_; + eval { $code->(); }; + like ( $EVAL_ERROR, $pat, $msg ); +} + +{ + package Metatest; + use Lmo; + + has stuff => ( is => 'rw', required => 1 ); + has init_stuff1 => ( is => 'rw', init_arg => undef ); + has init_stuff2 => ( is => 'rw', init_arg => 'fancy_name' ); +} +{ +package Metatest::child; + use Lmo; + extends 'Metatest'; + + has more_stuff => ( is => 'rw' ); +} + +my $obj = Metatest->new( stuff => 100 ); + +can_ok($obj, 'meta'); + +my $meta = $obj->meta(); + +is_deeply( + [ sort $meta->attributes ], + [ sort qw(stuff init_stuff1 init_stuff2) ], + "->attributes works" +); + +is_deeply( + [ sort $meta->attributes_for_new ], + [ sort qw(stuff fancy_name) ], + "->attributes_for_new works" +); + +# Do these BEFORE initializing ::extends +my $meta2 = Metatest::child->meta(); +is_deeply( + [ sort $meta2->attributes ], + [ sort qw(stuff init_stuff1 init_stuff2 more_stuff) ], + "->attributes works on a child class" +); + +is_deeply( + [ sort $meta2->attributes_for_new ], + [ sort qw(stuff fancy_name more_stuff) ], + "->attributes_for_new works in a child class" +); + +my $meta3 = Metatest::child->new(stuff => 10)->meta(); +is_deeply( + [ sort $meta3->attributes ], + [ sort qw(stuff init_stuff1 init_stuff2 more_stuff) ], + "->attributes works on an initialized child class" +); + +is_deeply( + [ sort $meta3->attributes_for_new ], + [ sort qw(stuff fancy_name more_stuff) ], + "->attributes_for_new works in an initialized child class" +); + +throws_ok { Metatest::child->new() } qr/\QAttribute (stuff) is required for Metatest::child/; + +done_testing; diff --git a/t/lib/Lmo/meta.t.moved b/t/lib/Lmo/meta.t.moved new file mode 100644 index 00000000..40106511 --- /dev/null +++ b/t/lib/Lmo/meta.t.moved @@ -0,0 +1,83 @@ +#!/usr/bin/perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +sub throws_ok (&;$) { + my ( $code, $pat, $msg ) = @_; + eval { $code->(); }; + like ( $EVAL_ERROR, $pat, $msg ); +} + +{ + package Metatest; + use Lmo; + + has stuff => ( is => 'rw', required => 1 ); + has init_stuff1 => ( is => 'rw', init_arg => undef ); + has init_stuff2 => ( is => 'rw', init_arg => 'fancy_name' ); +} +{ +package Metatest::child; + use Lmo; + extends 'Metatest'; + + has more_stuff => ( is => 'rw' ); +} + +my $obj = Metatest->new( stuff => 100 ); + +can_ok($obj, 'meta'); + +my $meta = $obj->meta(); + +is_deeply( + [ sort $meta->attributes ], + [ sort qw(stuff init_stuff1 init_stuff2) ], + "->attributes works" +); + +is_deeply( + [ sort $meta->attributes_for_new ], + [ sort qw(stuff fancy_name) ], + "->attributes_for_new works" +); + +# Do these BEFORE initializing ::extends +my $meta2 = Metatest::child->meta(); +is_deeply( + [ sort $meta2->attributes ], + [ sort qw(stuff init_stuff1 init_stuff2 more_stuff) ], + "->attributes works on a child class" +); + +is_deeply( + [ sort $meta2->attributes_for_new ], + [ sort qw(stuff fancy_name more_stuff) ], + "->attributes_for_new works in a child class" +); + +my $meta3 = Metatest::child->new(stuff => 10)->meta(); +is_deeply( + [ sort $meta3->attributes ], + [ sort qw(stuff init_stuff1 init_stuff2 more_stuff) ], + "->attributes works on an initialized child class" +); + +is_deeply( + [ sort $meta3->attributes_for_new ], + [ sort qw(stuff fancy_name more_stuff) ], + "->attributes_for_new works in an initialized child class" +); + +throws_ok { Metatest::child->new() } qr/\QAttribute (stuff) is required for Metatest::child/; + +done_testing; diff --git a/t/lib/Mo/object.t b/t/lib/Lmo/object.t similarity index 90% rename from t/lib/Mo/object.t rename to t/lib/Lmo/object.t index 37a71ea4..c54266c9 100644 --- a/t/lib/Mo/object.t +++ b/t/lib/Lmo/object.t @@ -10,7 +10,7 @@ use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); use Test::More; -use lib "$ENV{PERCONA_TOOLKIT_BRANCH}/t/lib/Mo"; +use lib "$ENV{PERCONA_TOOLKIT_BRANCH}/t/lib/Lmo"; { package Clean; use Foo; } diff --git a/t/lib/Mo/required.t b/t/lib/Lmo/required.t similarity index 86% rename from t/lib/Mo/required.t rename to t/lib/Lmo/required.t index b7319317..7ef93ff1 100644 --- a/t/lib/Mo/required.t +++ b/t/lib/Lmo/required.t @@ -13,14 +13,14 @@ use Test::More; #============ package Foo::required; -use Mo qw(required); +use Lmo qw(required); has 'stuff' => (required => 1); has 'stuff2' => (required => 1); has 'foo' => (); #============ package Foo::required_is; -use Mo qw(required); +use Lmo qw(required); has 'stuff' => (required => 1, is => 'ro'); #============ @@ -28,7 +28,7 @@ has 'stuff' => (required => 1, is => 'ro'); package main; my $f0 = eval { Foo::required->new(stuff2 => 'foobar') }; -like $@, qr/^\QAttribute (stuff) is required/, 'Mo dies when a required value is not provided'; +like $@, qr/^\QAttribute (stuff) is required/, 'Lmo dies when a required value is not provided'; my $f = Foo::required->new(stuff => 'fubar', stuff2 => 'foobar'); is $f->stuff, 'fubar', 'Object is correctly initialized when required values are provided'; diff --git a/t/lib/Lmo/role.t b/t/lib/Lmo/role.t new file mode 100644 index 00000000..10345885 --- /dev/null +++ b/t/lib/Lmo/role.t @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +BEGIN { + my $have_roles = eval { require Role::Tiny }; + plan skip_all => "Can't load Role::Tiny, not testing Roles" + unless $have_roles; +} + +{ + package One::P1; use Lmo::Role; + has two => (is => 'ro', default => sub { 'two' }); + no Lmo::Role; + + package One::P2; use Lmo::Role; + has three => (is => 'ro', default => sub { 'three' }); + no Lmo::Role; + + package One::P3; use Lmo::Role; + has four => (is => 'ro', default => sub { 'four' }); + no Lmo::Role; + + package One; use Lmo; + with qw( One::P1 One::P2 ); + has one => (is => 'ro', default => sub { 'one' }); +} + +my $combined = One->new(); + +ok $combined->does($_), "Does $_" for qw(One::P1 One::P2); + +ok !$combined->does($_), "Doesn't $_" for qw(One::P3 One::P4); + +is $combined->one, "one", "attr default set from class"; +is $combined->two, "two", "attr default set from role"; +is $combined->three, "three", "attr default set from role"; + +# Testing unimport + +{ + package Two::P1; use Lmo::Role; + has two => (is => 'ro', default => sub { 'two' }); + no Lmo::Role; + + package Two; use Lmo; + with qw(Two::P1); + has three => ( is => 'ro', default => sub { 'three' } ); + no Lmo; +} + +my $two = Two->new(); + +is + $two->two(), + 'two', + "unimporting in a role doesn't remove new attributes"; + +for my $class ( qw( Two::P1 Two ) ) { + ok !$class->can($_), "...but does remove $_ from $class" for qw(has with extends requires); +} + +done_testing; diff --git a/t/lib/Lmo/role.t.moved b/t/lib/Lmo/role.t.moved new file mode 100644 index 00000000..10345885 --- /dev/null +++ b/t/lib/Lmo/role.t.moved @@ -0,0 +1,72 @@ +#!/usr/bin/perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +BEGIN { + my $have_roles = eval { require Role::Tiny }; + plan skip_all => "Can't load Role::Tiny, not testing Roles" + unless $have_roles; +} + +{ + package One::P1; use Lmo::Role; + has two => (is => 'ro', default => sub { 'two' }); + no Lmo::Role; + + package One::P2; use Lmo::Role; + has three => (is => 'ro', default => sub { 'three' }); + no Lmo::Role; + + package One::P3; use Lmo::Role; + has four => (is => 'ro', default => sub { 'four' }); + no Lmo::Role; + + package One; use Lmo; + with qw( One::P1 One::P2 ); + has one => (is => 'ro', default => sub { 'one' }); +} + +my $combined = One->new(); + +ok $combined->does($_), "Does $_" for qw(One::P1 One::P2); + +ok !$combined->does($_), "Doesn't $_" for qw(One::P3 One::P4); + +is $combined->one, "one", "attr default set from class"; +is $combined->two, "two", "attr default set from role"; +is $combined->three, "three", "attr default set from role"; + +# Testing unimport + +{ + package Two::P1; use Lmo::Role; + has two => (is => 'ro', default => sub { 'two' }); + no Lmo::Role; + + package Two; use Lmo; + with qw(Two::P1); + has three => ( is => 'ro', default => sub { 'three' } ); + no Lmo; +} + +my $two = Two->new(); + +is + $two->two(), + 'two', + "unimporting in a role doesn't remove new attributes"; + +for my $class ( qw( Two::P1 Two ) ) { + ok !$class->can($_), "...but does remove $_ from $class" for qw(has with extends requires); +} + +done_testing; diff --git a/t/lib/Mo/strict.t b/t/lib/Lmo/strict.t similarity index 87% rename from t/lib/Mo/strict.t rename to t/lib/Lmo/strict.t index eb98e4dd..9e3e0b5c 100644 --- a/t/lib/Mo/strict.t +++ b/t/lib/Lmo/strict.t @@ -11,9 +11,9 @@ use warnings FATAL => 'all'; use English qw(-no_match_vars); use Test::More; -eval 'package Foo; use Mo; $x = 1'; +eval 'package Foo; use Lmo; $x = 1'; like $@, qr/Global symbol "\$x" requires explicit package name/, - 'Mo is strict'; + 'Lmo is strict'; done_testing; diff --git a/t/lib/Mo/test.t b/t/lib/Lmo/test.t similarity index 85% rename from t/lib/Mo/test.t rename to t/lib/Lmo/test.t index 87682a31..0772900e 100644 --- a/t/lib/Mo/test.t +++ b/t/lib/Lmo/test.t @@ -13,18 +13,18 @@ use Test::More; #============ package Foo; -use Mo; +use Lmo; has 'this'; #============ package main; -ok defined(&Foo::has), 'Mo exports has'; -ok defined(&Foo::extends), 'Mo exports extends'; -ok not(defined(&Foo::new)), 'Mo does not export new'; -ok 'Foo'->isa('Mo::Object'), 'Foo isa Mo::Object'; -is "@Foo::ISA", "Mo::Object", '@Foo::ISA is Mo::Object'; +ok defined(&Foo::has), 'Lmo exports has'; +ok defined(&Foo::extends), 'Lmo exports extends'; +ok not(defined(&Foo::new)), 'Lmo does not export new'; +ok 'Foo'->isa('Lmo::Object'), 'Foo isa Lmo::Object'; +is "@Foo::ISA", "Lmo::Object", '@Foo::ISA is Lmo::Object'; ok 'Foo'->can('new'), 'Foo can new'; ok 'Foo'->can('this'), 'Foo can this'; @@ -50,7 +50,7 @@ ok not(defined($f->{this})), '{this} is not defined'; #============ package Bar; -use Mo 'builder', 'default'; +use Lmo 'builder', 'default'; extends 'Foo'; has 'that'; @@ -70,7 +70,7 @@ has guess => ( #============ package main; -ok 'Bar'->isa('Mo::Object'), 'Bar isa Mo::Object'; +ok 'Bar'->isa('Lmo::Object'), 'Bar isa Lmo::Object'; ok 'Bar'->isa('Foo'), 'Bar isa Foo'; is "@Bar::ISA", 'Foo', '@Bar::ISA is Foo'; ok 'Bar'->can('new'), 'Bar can new'; @@ -85,7 +85,7 @@ my $b = Bar->new( is ref($b), 'Bar', 'Object created'; ok $b->isa('Foo'), 'Inheritance works'; -ok $b->isa('Mo::Object'), 'Bar isa Mo::Object since Foo isa Mo::Object'; +ok $b->isa('Lmo::Object'), 'Bar isa Lmo::Object since Foo isa Lmo::Object'; is $b->this, 'thing', 'Read works in parent class'; is $b->that, 'thong', 'Read works in current class'; is ref($b->them), 'ARRAY', 'default works'; @@ -103,7 +103,7 @@ is $b->guess, 'me me me', 'default trumps builder'; #============ package Baz; -use Mo 'build'; +use Lmo 'build'; has 'foo'; @@ -114,7 +114,7 @@ sub BUILD { #============ package Maz; -use Mo; +use Lmo; extends 'Baz'; has 'bar'; diff --git a/t/lib/Lmo/unimport.t b/t/lib/Lmo/unimport.t new file mode 100644 index 00000000..f40d4485 --- /dev/null +++ b/t/lib/Lmo/unimport.t @@ -0,0 +1,28 @@ +#!/usr/bin/perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +{ + package One; use Lmo; + has one => (is => 'ro', default => sub { 'one' }); + no Lmo; +} + +my $unimported = One->new(); +is + $unimported->one(), + 'one', + "after unimporting, ->one still works"; + +ok !$unimported->can($_), "after unimpoirt, can't $_" for qw(has with extends); + +done_testing; diff --git a/t/lib/Lmo/unimport.t.moved b/t/lib/Lmo/unimport.t.moved new file mode 100644 index 00000000..f40d4485 --- /dev/null +++ b/t/lib/Lmo/unimport.t.moved @@ -0,0 +1,28 @@ +#!/usr/bin/perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +{ + package One; use Lmo; + has one => (is => 'ro', default => sub { 'one' }); + no Lmo; +} + +my $unimported = One->new(); +is + $unimported->one(), + 'one', + "after unimporting, ->one still works"; + +ok !$unimported->can($_), "after unimpoirt, can't $_" for qw(has with extends); + +done_testing; diff --git a/t/lib/MySQLProtocolParser.t b/t/lib/MySQLProtocolParser.t index 5b3fc54c..e63d2647 100644 --- a/t/lib/MySQLProtocolParser.t +++ b/t/lib/MySQLProtocolParser.t @@ -9,7 +9,7 @@ BEGIN { use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); -use Test::More tests => 72; +use Test::More; use MySQLProtocolParser; use TcpdumpParser; @@ -38,7 +38,6 @@ test_protocol_parser( pos_in_log => 0, bytes => length('select "hello world" as greeting'), cmd => 'Query', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -66,7 +65,6 @@ test_protocol_parser( pos_in_log => 1470, bytes => length('administrator command: Connect'), cmd => 'Admin', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -84,7 +82,6 @@ test_protocol_parser( pos_in_log => 2449, ts => '090412 11:00:13.118643', user => 'msandbox', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -102,7 +99,6 @@ test_protocol_parser( pos_in_log => 3298, ts => '090412 11:00:13.119079', user => 'msandbox', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -120,7 +116,6 @@ test_protocol_parser( pos_in_log => '4186', ts => '090412 11:00:13.119487', user => 'msandbox', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -177,7 +172,7 @@ test_protocol_parser( pos_in_log => 0, bytes => length('select 5 from foo'), cmd => 'Query', - Error_no => "#1046", + Error_no => "1046", Error_msg => 'No database selected', Rows_affected => 0, Warning_count => 0, @@ -194,7 +189,7 @@ test_protocol_parser( protocol => $protocol, file => "$sample/tcpdump005.txt", result => [ - { Error_no => 'none', + { Rows_affected => 1, Query_time => '0.000435', Thread_id => 4294967296, @@ -212,7 +207,7 @@ test_protocol_parser( No_good_index_used => 'No', No_index_used => 'No', }, - { Error_no => 'none', + { Rows_affected => 2, Query_time => '0.000565', Thread_id => 4294967296, @@ -252,7 +247,6 @@ test_protocol_parser( pos_in_log => 0, bytes => length('select * from t'), cmd => 'Query', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -280,7 +274,6 @@ test_protocol_parser( pos_in_log => 0, bytes => length('insert into t values(current_date)'), cmd => 'Query', - Error_no => 'none', Rows_affected => 1, Warning_count => 1, No_good_index_used => 'No', @@ -412,7 +405,6 @@ test_protocol_parser( pos_in_log => 0, bytes => length('select "hello world" as greeting'), cmd => 'Query', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -434,7 +426,7 @@ test_protocol_parser( file => "$sample/tcpdump013.txt", desc => 'old password and compression', result => [ - { Error_no => 'none', + { No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.034355', @@ -466,7 +458,6 @@ test_protocol_parser( desc => 'in-stream compression detection', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.001375', @@ -503,7 +494,6 @@ SKIP: { desc => 'compressed data', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.006415', @@ -522,7 +512,6 @@ SKIP: { user => 'msandbox', }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'Yes', Query_time => '0.002884', @@ -541,7 +530,6 @@ SKIP: { user => 'msandbox', }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000000', @@ -574,7 +562,6 @@ test_protocol_parser( desc => 'TCP retransmission', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.001000', @@ -607,7 +594,6 @@ test_protocol_parser( desc => 'Multiple servers', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000206', @@ -626,7 +612,6 @@ test_protocol_parser( user => undef, }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000203', @@ -656,7 +641,6 @@ test_protocol_parser( desc => 'Multiple servers but watch only one', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000206', @@ -713,7 +697,6 @@ test_protocol_parser( desc => 'prepared statements, simple, no NULL', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000286', @@ -733,7 +716,6 @@ test_protocol_parser( Statement_id => 2, }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'Yes', Query_time => '0.000281', @@ -753,7 +735,6 @@ test_protocol_parser( Statement_id => 2, }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000000', @@ -782,7 +763,6 @@ test_protocol_parser( desc => 'prepared statements, NULL value', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000303', @@ -802,7 +782,6 @@ test_protocol_parser( Statement_id => 2, }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000186', @@ -832,7 +811,6 @@ test_protocol_parser( desc => 'prepared statements, string, char and float', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000315', @@ -852,7 +830,6 @@ test_protocol_parser( Statement_id => 2, }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000249', @@ -882,7 +859,6 @@ test_protocol_parser( desc => 'prepared statements, all NULL', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000278', @@ -902,7 +878,6 @@ test_protocol_parser( Statement_id => 2, }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000159', @@ -932,7 +907,6 @@ test_protocol_parser( desc => 'prepared statements, no params', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000268', @@ -952,7 +926,6 @@ test_protocol_parser( Statement_id => 2, }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'Yes', Query_time => '0.000234', @@ -982,7 +955,6 @@ test_protocol_parser( desc => 'prepared statements, close statement', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000000', @@ -1011,7 +983,6 @@ test_protocol_parser( desc => 'prepared statements, reset statement', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000023', @@ -1041,7 +1012,6 @@ test_protocol_parser( desc => 'prepared statements, multiple exec, new param', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000292', @@ -1061,7 +1031,6 @@ test_protocol_parser( user => undef }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'Yes', Query_time => '0.000254', @@ -1081,7 +1050,6 @@ test_protocol_parser( user => undef }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'Yes', Query_time => '0.000190', @@ -1101,7 +1069,6 @@ test_protocol_parser( user => undef }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'Yes', Query_time => '0.000166', @@ -1131,7 +1098,6 @@ test_protocol_parser( desc => 'prepared statements, real param types', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000221', @@ -1151,7 +1117,6 @@ test_protocol_parser( user => undef }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000203', @@ -1171,7 +1136,6 @@ test_protocol_parser( user => undef }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000000', @@ -1190,7 +1154,6 @@ test_protocol_parser( user => undef }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000000', @@ -1219,7 +1182,6 @@ test_protocol_parser( desc => 'prepared statements, ok response to execute', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000046', @@ -1239,7 +1201,6 @@ test_protocol_parser( user => undef }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000024', @@ -1269,7 +1230,6 @@ test_protocol_parser( desc => 'prepared statements, NULL bitmap', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000288', @@ -1289,7 +1249,6 @@ test_protocol_parser( user => undef }, { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000322', @@ -1322,7 +1281,6 @@ test_protocol_parser( desc => 'issue 761', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000431', @@ -1354,7 +1312,6 @@ test_protocol_parser( desc => 'issue 760', result => [ { - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000430', @@ -1397,7 +1354,6 @@ test_protocol_parser( pos_in_log => 1470, bytes => length('administrator command: Connect'), cmd => 'Admin', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -1415,7 +1371,6 @@ test_protocol_parser( pos_in_log => 2449, ts => '090412 11:00:13.119079', user => 'msandbox', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -1433,7 +1388,6 @@ test_protocol_parser( pos_in_log => 3337, ts => '090412 11:00:13.119487', user => 'msandbox', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -1441,7 +1395,6 @@ test_protocol_parser( }, # port reused... { ts => '090412 12:00:00.800000', - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.700000', @@ -1459,7 +1412,6 @@ test_protocol_parser( user => 'msandbox', }, { ts => '090412 12:00:01.000000', - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.100000', @@ -1477,7 +1429,6 @@ test_protocol_parser( user => 'msandbox', }, { ts => '090412 12:00:01.100000', - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000000', @@ -1516,7 +1467,6 @@ test_protocol_parser( pos_in_log => 1470, bytes => length('administrator command: Connect'), cmd => 'Admin', - Error_no => 'none', Rows_affected => 0, Warning_count => 0, No_good_index_used => 'No', @@ -1524,7 +1474,6 @@ test_protocol_parser( }, # port reused... { ts => '090412 12:00:00.800000', - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.700000', @@ -1542,7 +1491,6 @@ test_protocol_parser( user => 'msandbox', }, { ts => '090412 12:00:01.000000', - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.100000', @@ -1560,7 +1508,6 @@ test_protocol_parser( user => 'msandbox', }, { ts => '090412 12:00:01.100000', - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000000', @@ -1588,7 +1535,6 @@ test_protocol_parser( desc => 'no server ok (issue 794)', result => [ { ts => '090412 12:00:01.000000', - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000000', @@ -1606,7 +1552,6 @@ test_protocol_parser( user => undef }, { ts => '090412 12:00:03.000000', - Error_no => 'none', No_good_index_used => 'No', No_index_used => 'No', Query_time => '1.000000', @@ -1659,7 +1604,7 @@ test_protocol_parser( [ { Error_msg => "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1", - Error_no => '#1064', + Error_no => '1064', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000316', @@ -1679,7 +1624,7 @@ test_protocol_parser( }, { Error_msg => 'Unknown system variable \'nono\'', - Error_no => '#1193', + Error_no => '1193', No_good_index_used => 'No', No_index_used => 'No', Query_time => '0.000329', @@ -1700,7 +1645,107 @@ test_protocol_parser( ], ); +# ############################################################################# +# Bug 1103045: pt-query-digest fails to parse non-SQL errors +# https://bugs.launchpad.net/percona-toolkit/+bug/1103045 +# ############################################################################# + +$protocol = new MySQLProtocolParser( + server => '127.0.0.1', + port => '12345', +); + +test_protocol_parser( + parser => $tcpdump, + protocol => $protocol, + file => "$sample/tcpdump043.txt", + desc => 'Bad connection', + result => + [ + { + Error_msg => 'Got packets out of order', + Error_no => 1156, + No_good_index_used => 'No', + No_index_used => 'No', + Query_time => '3.536306', + Rows_affected => 0, + Thread_id => 27, + Warning_count => 0, + arg => 'administrator command: Connect', + bytes => 30, + cmd => 'Admin', + db => undef, + host => '127.0.0.1', + ip => '127.0.0.1', + port => '62160', + pos_in_log => undef, + ts => '130124 13:03:28.672987', + user => undef, + } + ], +); + +test_protocol_parser( + parser => $tcpdump, + protocol => $protocol, + file => "$sample/tcpdump042.txt", + desc => 'Client went away during handshake', + result => [ + { + No_good_index_used => 'No', + No_index_used => 'No', + Query_time => '9.998411', + Rows_affected => 0, + Thread_id => 24, + Warning_count => 0, + arg => 'administrator command: Connect', + bytes => 30, + cmd => 'Admin', + db => undef, + host => '127.0.0.1', + ip => '127.0.0.1', + port => '62133', + pos_in_log => undef, + ts => '130124 12:55:48.274417', + user => undef, + Error_msg => 'Client closed connection during handshake', + } + ], +); + +$protocol = new MySQLProtocolParser( + server => '100.0.0.1', +); + +test_protocol_parser( + parser => $tcpdump, + protocol => $protocol, + file => "$sample/tcpdump044.txt", + desc => 'Client aborted connection (bug 1103045)', + result => [ + { + No_good_index_used => 'No', + No_index_used => 'No', + Query_time => '3.819507', + Rows_affected => 0, + Thread_id => 13, + Warning_count => 0, + arg => 'administrator command: Connect', + bytes => 30, + cmd => 'Admin', + db => undef, + host => '100.0.0.2', + ip => '100.0.0.2', + port => '44432', + pos_in_log => undef, + ts => '130122 09:55:57.793375', + user => undef, + Error_msg => 'Client closed connection during handshake', + }, + ], +); + # ############################################################################# # Done. # ############################################################################# -exit; +done_testing; diff --git a/t/lib/Pipeline.t b/t/lib/Pipeline.t index 6cb5f0c3..dc21af96 100644 --- a/t/lib/Pipeline.t +++ b/t/lib/Pipeline.t @@ -261,7 +261,7 @@ $pipeline->add( ); $output = output( - sub { $pipeline->execute(%args) }, + sub {$pipeline->execute(%args); }, stderr => 1, ); diff --git a/t/lib/QueryReportFormatter.t b/t/lib/QueryReportFormatter.t index 7677df36..66442c63 100644 --- a/t/lib/QueryReportFormatter.t +++ b/t/lib/QueryReportFormatter.t @@ -43,7 +43,6 @@ my $o = new OptionParser(description=>'qrf'); my $ex = new ExplainAnalyzer(QueryRewriter => $qr, QueryParser => $qp); $o->get_specs("$trunk/bin/pt-query-digest"); - my $qrf = new QueryReportFormatter( OptionParser => $o, QueryRewriter => $qr, @@ -885,6 +884,13 @@ ok( # Test show_all. @ARGV = qw(--show-all host); $o->get_opts(); +$qrf = new QueryReportFormatter( + OptionParser => $o, + QueryRewriter => $qr, + QueryParser => $qp, + Quoter => $q, + ExplainAnalyzer => $ex, +); $result = $qrf->event_report( ea => $ea, select => [ qw(Query_time host) ], @@ -971,7 +977,13 @@ $ea->calculate_statistical_metrics(apdex_t=>1); # Reset opts in case anything above left something set. @ARGV = qw(); $o->get_opts(); - +$qrf = new QueryReportFormatter( + OptionParser => $o, + QueryRewriter => $qr, + QueryParser => $qp, + Quoter => $q, + ExplainAnalyzer => $ex, +); # Normally, the report subs will make their own ReportFormatter but # that package isn't visible to QueryReportFormatter right now so we # make ReportFormatters and pass them in. Since ReporFormatters can't @@ -980,7 +992,7 @@ $o->get_opts(); # profile subreport. And the line width is 82 because that's the new # default to accommodate the EXPLAIN sparkline (issue 1141). my $report = new ReportFormatter(line_width=>82); -$qrf->set_report_formatter(report=>'profile', formatter=>$report); +$qrf->{formatter} = $report; ok( no_diff( sub { $qrf->print_reports( @@ -997,8 +1009,6 @@ ok( "print_reports(header, query_report, profile)" ); -$report = new ReportFormatter(line_width=>82); -$qrf->set_report_formatter(report=>'profile', formatter=>$report); ok( no_diff( sub { $qrf->print_reports( @@ -1051,11 +1061,6 @@ foreach my $event ( @$events ) { $ea->aggregate($event); } $ea->calculate_statistical_metrics(); -$report = new ReportFormatter( - line_width => 82, - extend_right => 1, -); -$qrf->set_report_formatter(report=>'prepared', formatter=>$report); ok( no_diff( sub { @@ -1094,11 +1099,6 @@ foreach my $event ( @$events ) { $ea->aggregate($event); } $ea->calculate_statistical_metrics(); -$report = new ReportFormatter( - line_width => 82, - extend_right => 1, -); -$qrf->set_report_formatter(report=>'profile', formatter=>$report); ok( no_diff( sub { @@ -1130,7 +1130,13 @@ SKIP: { @ARGV = qw(--explain F=/tmp/12345/my.sandbox.cnf); $o->get_opts(); - + $qrf = new QueryReportFormatter( + OptionParser => $o, + QueryRewriter => $qr, + QueryParser => $qp, + Quoter => $q, + ExplainAnalyzer => $ex, + ); my $qrf = new QueryReportFormatter( OptionParser => $o, QueryRewriter => $qr, @@ -1151,70 +1157,6 @@ SKIP: { "explain_report()" ); - my $arg = "select t1.i from t as t1 join t as t2 where t1.i < t2.i and t1.v is not null order by t1.i"; - my $fingerprint = $qr->fingerprint($arg); - - $events = [ - { - Query_time => '0.000286', - arg => $arg, - fingerprint => $fingerprint, - bytes => length $arg, - cmd => 'Query', - db => 'qrf', - pos_in_log => 0, - ts => '091208 09:23:49.637394', - }, - ]; - $ea = new EventAggregator( - groupby => 'fingerprint', - worst => 'Query_time', - ); - foreach my $event ( @$events ) { - $ea->aggregate($event); - } - $ea->calculate_statistical_metrics(); - - # Make sure that explain_sparkline() does USE db like explain_report() - # does because by mqd defaults expalin_sparline() is called by profile() - # so if it doesn't USE db then the EXPLAIN will fail. Here we reset - # the db to something else because we already called explain_report() - # above which did USE qrf. - # - # 5.6 really is that different: ia vs. TF>aI. It's smarter. - $dbh->do("USE mysql"); - my $explain_sparkline = $qrf->explain_sparkline($arg, 'qrf'); - is( - $explain_sparkline, - $sandbox_version eq '5.6' ? "ia" : "TF>aI", - "explain_sparkling() uses db" - ); - - $report = new ReportFormatter( - line_width => 82, - extend_right => 1, - ); - $qrf->set_report_formatter(report=>'profile', formatter=>$report); - $dbh->do("USE mysql"); # same reason as above ^; force use db from event - ok( - no_diff( - sub { - $qrf->print_reports( - reports => ['profile', 'query_report'], - ea => $ea, - worst => [ [$fingerprint, 'top', 1], ], - other => [ [$fingerprint, 'misc', 2], ], - orderby => 'Query_time', - groupby => 'fingerprint', - ); - }, - ( $sandbox_version eq '5.6' ? "t/lib/samples/QueryReportFormatter/report032.txt" - : $sandbox_version ge '5.1' ? "t/lib/samples/QueryReportFormatter/report027.txt" - : "t/lib/samples/QueryReportFormatter/report029.txt"), - ), - "EXPLAIN sparkline (issue 1141)" - ); - $sb->wipe_clean($dbh); $dbh->disconnect(); } @@ -1265,7 +1207,6 @@ foreach my $event ( @$events ) { $ea->calculate_statistical_metrics(); @ARGV = qw(); $o->get_opts(); -$report = new ReportFormatter(line_width=>82); $qrf = new QueryReportFormatter( OptionParser => $o, QueryRewriter => $qr, @@ -1273,7 +1214,6 @@ $qrf = new QueryReportFormatter( Quoter => $q, ExplainAnalyzer => $ex, ); -$qrf->set_report_formatter(report=>'profile', formatter=>$report); my $output = output( sub { $qrf->print_reports( reports => [qw(rusage date files header query_report profile)], @@ -1337,11 +1277,6 @@ foreach my $event ( @$events ) { $ea->aggregate($event); } $ea->calculate_statistical_metrics(); -$report = new ReportFormatter( - line_width => 82, - extend_right => 1, -); -$qrf->set_report_formatter(report=>'profile', formatter=>$report); ok( no_diff( sub { @@ -1360,181 +1295,6 @@ ok( "Variance-to-mean ration (issue 1124)" ); -# ############################################################################# -# Issue 1141: Add "spark charts" to mk-query-digest profile -# ############################################################################# -sub proc_events { - my ( %args ) = @_; - my ($arg, $attrib, $vals) = @args{qw(arg attrib vals)}; - - my $bytes = length $arg; - my $fingerprint = $qr->fingerprint($arg); - - $events = []; - foreach my $val ( @$vals ) { - push @$events, { - bytes => $bytes, - arg => $arg, - fingerprint => $fingerprint, - $attrib => $val, - } - } - - $ea = new EventAggregator( - groupby => 'fingerprint', - worst => 'Query_time', - ); - foreach my $event (@$events) { - $ea->aggregate($event); - } - $ea->calculate_statistical_metrics(apdex_t=>1); - - # Seeing the full chart helps determine what the - # sparkline should look like. - if ( $args{chart} ) { - $result = $qrf->chart_distro( - ea => $ea, - item => 'select c from t', - attrib => 'Query_time', - ); - print $result; - } - - return; -}; - -# Test sparklines in isolation. -proc_events( - arg => 'select c from t', - attrib => 'Query_time', - vals => [qw(0 0 0)], -); -$result = $qrf->distro_sparkline( - ea => $ea, - item => 'select c from t', - attrib => 'Query_time', -); -is( - $result, - " ", - "Sparkchart line - all zeros" -); - -# 1us -# 10us -# 100us ################################################ -# 1ms ################################ -# 10ms ################################ -# 100ms ################################################################ -# 1s ################ -# 10s+ -proc_events( - arg => 'select c from t', - attrib => 'Query_time', - vals => [qw(0.100000 0.500000 0.000600 0.008000 0.990000 1.000000 0.400000 0.003000 0.000200 0.000100 0.010000 0.020000)], -); -$result = $qrf->distro_sparkline( - ea => $ea, - item => 'select c from t', - attrib => 'Query_time', -); -is( - $result, - " -..^_ ", - "Sparkchart line 1" -); - -# 1us -# 10us -# 100us -# 1ms -# 10ms ################################ -# 100ms ################################################################ -# 1s ######## -# 10s+ -proc_events( - arg => 'select c from t', - attrib => 'Query_time', - vals => [qw(0.01 0.03 0.08 0.09 0.3 0.5 0.5 0.6 0.7 0.5 0.5 0.9 1.0)], -); -$result = $qrf->distro_sparkline( - ea => $ea, - item => 'select c from t', - attrib => 'Query_time', -); -is( - $result, - " .^_ ", - "Sparkchart line 2" -); - -# 1us ################################################################ -# 10us ################################################################ -# 100us ################################################################ -# 1ms ################################################################ -# 10ms ################################################################ -# 100ms ################################################################ -# 1s ################################################################ -# 10s+ -proc_events( - arg => 'select c from t', - attrib => 'Query_time', - vals => [qw(0.000003 0.000030 0.000300 0.003000 0.030000 0.300000 3)], -); -$result = $qrf->distro_sparkline( - ea => $ea, - item => 'select c from t', - attrib => 'Query_time', -); -is( - $result, - "^^^^^^^ ", - "Sparkchart line - vals in all ranges except 10s+" -); - - -# 1us ################################################################ -# 10us ################################################################ -# 100us -# 1ms -# 10ms -# 100ms -# 1s ################################################################ -# 10s+ ################################################################ -proc_events( - arg => 'select c from t', - attrib => 'Query_time', - vals => [qw(0.000003 0.000030 0.000003 0.000030 3 3 30 30)], -); -$result = $qrf->distro_sparkline( - ea => $ea, - item => 'select c from t', - attrib => 'Query_time', -); -is( - $result, - "^^ ^^", - "Sparkchart line - twin peaks" -); - -# Test that that ^ sparkchart appears in the event header properly. -$result = $qrf->event_report( - ea => $ea, - select => [ qw(Query_time) ], - item => 'select c from t', - rank => 1, - orderby => 'Query_time', - reason => 'top', -); -ok( - no_diff( - $result, - "t/lib/samples/QueryReportFormatter/report028.txt", - cmd_output => 1, - ), - 'Sparkchart in event header' -); - # ############################################################################ # Bug 887688: Prepared statements crash pt-query-digest # ############################################################################ @@ -1565,11 +1325,6 @@ foreach my $event ( @$events ) { $ea->aggregate($event); } $ea->calculate_statistical_metrics(); -$report = new ReportFormatter( - line_width => 82, - extend_right => 1, -); -$qrf->set_report_formatter(report=>'prepared', formatter=>$report); ok( no_diff( sub { diff --git a/t/lib/QueryReview.t b/t/lib/QueryReview.t index c5bba0c1..950953d4 100644 --- a/t/lib/QueryReview.t +++ b/t/lib/QueryReview.t @@ -161,7 +161,6 @@ my $hist_struct = $tp->parse( $qv->set_history_options( table => 'test.query_review_history', - dbh => $dbh, quoter => $q, tbl_struct => $hist_struct, col_pat => qr/^(.*?)_($pat)$/, @@ -257,7 +256,6 @@ $hist_struct = $tp->parse( $tp->get_create_table($dbh, 'test', 'query_review_history')); $qv->set_history_options( table => 'test.query_review_history', - dbh => $dbh, quoter => $q, tbl_struct => $hist_struct, col_pat => qr/^(.*?)_($pat)$/, diff --git a/t/lib/ReportFormatter.t b/t/lib/ReportFormatter.t index 744e85ad..7d69444a 100644 --- a/t/lib/ReportFormatter.t +++ b/t/lib/ReportFormatter.t @@ -88,7 +88,7 @@ is( # Basic report. # ############################################################################# $rf = new ReportFormatter(); -$rf->set_title('Checksum differences'); +$rf->title('Checksum differences'); $rf->set_columns( { name => 'Query ID', @@ -216,7 +216,7 @@ is( # Respect line width. # ############################################################################# $rf = new ReportFormatter(); -$rf->set_title('Respect line width'); +$rf->title('Respect line width'); $rf->set_columns( { name => 'col1' }, { name => 'col2' }, @@ -248,7 +248,7 @@ is( # extend_right # ############################################################################# $rf = new ReportFormatter(extend_right=>1); -$rf->set_title('extend_right'); +$rf->title('extend_right'); $rf->set_columns( { name => 'col1' }, { name => 'col2' }, @@ -280,7 +280,7 @@ is( # Relvative column widths. # ############################################################################# $rf = new ReportFormatter(); -$rf->set_title('Relative col widths'); +$rf->title('Relative col widths'); $rf->set_columns( { name => 'col1', width_pct=>'20', }, { name => 'col2', width_pct=>'40', }, @@ -309,7 +309,7 @@ is( ); $rf = new ReportFormatter(); -$rf->set_title('Relative col widths'); +$rf->title('Relative col widths'); $rf->set_columns( { name => 'col1', width_pct=>'20', }, { name => 'col2', width_pct=>'40', }, @@ -344,7 +344,7 @@ is( ); $rf = new ReportFormatter(); -$rf->set_title('Relative col widths'); +$rf->title('Relative col widths'); $rf->set_columns( { name => 'col1', width =>'25', }, { name => 'col2', width_pct=>'33', }, @@ -380,7 +380,7 @@ is( $rf = new ReportFormatter(); -$rf->set_title('Short cols'); +$rf->title('Short cols'); $rf->set_columns( { name => 'I am column1', }, { name => 'I am column2', }, @@ -403,7 +403,7 @@ is( ); $rf = new ReportFormatter(); -$rf->set_title('Short cols'); +$rf->title('Short cols'); $rf->set_columns( { name => 'I am column1', }, { name => 'I am column2', }, @@ -422,7 +422,7 @@ is( ); $rf = new ReportFormatter(); -$rf->set_title('Short cols'); +$rf->title('Short cols'); $rf->set_columns( { name => 'I am column1', }, { name => 'I am column2', }, diff --git a/t/lib/TimeSeriesTrender.t b/t/lib/TimeSeriesTrender.t deleted file mode 100644 index 605c9380..00000000 --- a/t/lib/TimeSeriesTrender.t +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/perl - -BEGIN { - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; -}; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); -use Test::More tests => 1; - -use TimeSeriesTrender; -use PerconaTest; - -my $result; -my $tst = new TimeSeriesTrender( - callback => sub { $result = $_[0]; }, -); - -$tst->set_time('5'); -map { $tst->add_number($_) } - qw(1 2 1 2 12 23 2 2 3 3 21 3 3 1 1 2 3 1 2 12 2 - 3 1 3 2 22 2 2 2 2 3 1 1); -$tst->set_time('6'); - -is_deeply($result, - { - ts => 5, - stdev => 6.09038140334414, - avg => 4.42424242424242, - min => 1, - max => 23, - cnt => 33, - sum => 146, - }, - 'Simple stats test'); - -# ############################################################################# -# Done. -# ############################################################################# diff --git a/t/lib/VersionCheck.t b/t/lib/VersionCheck.t index f5650c71..c00e54e0 100644 --- a/t/lib/VersionCheck.t +++ b/t/lib/VersionCheck.t @@ -12,7 +12,7 @@ use English qw(-no_match_vars); use Test::More; use Data::Dumper; -use VersionCheck; +use Pingback; use DSNParser; use Sandbox; use PerconaTest; @@ -23,7 +23,7 @@ my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); my $master_dbh = $sb->get_dbh_for('master'); my $slave1_dbh = $sb->get_dbh_for('slave1'); -my $vc = VersionCheck->new(); +my $vc = 'Pingback'; sub test_v { my (%args) = @_; diff --git a/t/lib/bash/log_warn_die.sh b/t/lib/bash/log_warn_die.sh index 8d71d089..49cbfcb1 100644 --- a/t/lib/bash/log_warn_die.sh +++ b/t/lib/bash/log_warn_die.sh @@ -1,17 +1,15 @@ #!/usr/bin/env bash -plan 6 - source "$LIB_DIR/log_warn_die.sh" -log "Hello world!" > $TEST_PT_TMPDIR/log +log "Hello world A!" > $TEST_PT_TMPDIR/log cmd_ok \ - "grep -q 'Hello world!' $TEST_PT_TMPDIR/log" \ + "grep -q 'Hello world A!' $TEST_PT_TMPDIR/log" \ "log msg" -log "Hello" "world!" > $TEST_PT_TMPDIR/log +log "Hello" "world B!" > $TEST_PT_TMPDIR/log cmd_ok \ - "grep -q 'Hello world!' $TEST_PT_TMPDIR/log" \ + "grep -q 'Hello world B!' $TEST_PT_TMPDIR/log" \ "log msg msg" is \ @@ -19,14 +17,14 @@ is \ "0" \ "Exit status 0" -warn "Hello world!" 2> $TEST_PT_TMPDIR/log +warn "Hello world C!" 2> $TEST_PT_TMPDIR/log cmd_ok \ - "grep -q 'Hello world!' $TEST_PT_TMPDIR/log" \ + "grep -q 'Hello world C!' $TEST_PT_TMPDIR/log" \ "warn msg" -warn "Hello" "world!" 2> $TEST_PT_TMPDIR/log +warn "Hello" "world D!" 2> $TEST_PT_TMPDIR/log cmd_ok \ - "grep -q 'Hello world!' $TEST_PT_TMPDIR/log" \ + "grep -q 'Hello world D!' $TEST_PT_TMPDIR/log" \ "warn msg msg" is \ @@ -34,6 +32,81 @@ is \ "1" \ "Exit status 1" +OPT_VERBOSE=1 + +info "Hello world 1!" > $TEST_PT_TMPDIR/log +file_is_empty \ + $TEST_PT_TMPDIR/log \ + "verbose=1 info" + +log "Hello world 2!" > $TEST_PT_TMPDIR/log +file_is_empty \ + $TEST_PT_TMPDIR/log \ + "verbose=1 log" + +warn "Hello world 3!" > $TEST_PT_TMPDIR/log 2>&1 +file_contains \ + $TEST_PT_TMPDIR/log \ + "Hello world 3!" \ + "verbose=1 warn" + +OPT_VERBOSE=2 + +info "Hello world 4!" > $TEST_PT_TMPDIR/log +file_is_empty \ + $TEST_PT_TMPDIR/log \ + "verbose=2 info" + +log "Hello world 5!" > $TEST_PT_TMPDIR/log +file_contains \ + $TEST_PT_TMPDIR/log \ + "Hello world 5!" \ + "verbose=2 log" + +warn "Hello world 6!" > $TEST_PT_TMPDIR/log 2>&1 +file_contains \ + $TEST_PT_TMPDIR/log \ + "Hello world 6!" \ + "verbose=2 warn" + +OPT_VERBOSE=3 + +info "Hello world 7!" > $TEST_PT_TMPDIR/log +file_contains \ + $TEST_PT_TMPDIR/log \ + "Hello world 7!" \ + "verbose=3 info" + +log "Hello world 8!" > $TEST_PT_TMPDIR/log +file_contains \ + $TEST_PT_TMPDIR/log \ + "Hello world 8!" \ + "verbose=3 log" + +warn "Hello world 9!" > $TEST_PT_TMPDIR/log 2>&1 +file_contains \ + $TEST_PT_TMPDIR/log \ + "Hello world 9!" \ + "verbose=3 warn" + +OPT_VERBOSE=0 + +info "Hello world 10!" > $TEST_PT_TMPDIR/log +file_is_empty \ + $TEST_PT_TMPDIR/log \ + "verbose=0 info" + +log "Hello world 11!" > $TEST_PT_TMPDIR/log +file_is_empty \ + $TEST_PT_TMPDIR/log \ + "verbose=0 log" + +warn "Hello world 12!" > $TEST_PT_TMPDIR/log 2>&1 +file_is_empty \ + $TEST_PT_TMPDIR/log \ + "verbose=0 warn" + # ########################################################################### # Done # ########################################################################### +done_testing diff --git a/t/lib/samples/QueryReportFormatter/report001.txt b/t/lib/samples/QueryReportFormatter/report001.txt index 304abd51..ceb1cfc0 100644 --- a/t/lib/samples/QueryReportFormatter/report001.txt +++ b/t/lib/samples/QueryReportFormatter/report001.txt @@ -7,8 +7,7 @@ # Lock time 1ms 1ms 1ms 1ms 1ms 0 1ms # Query 1: 0 QPS, 0x concurrency, ID 0x5796997451B1FA1D at byte 123 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -35,6 +34,6 @@ select col from tbl where id=42\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x5796997451B1FA1D 1.0007 100.0% 1 1.0007 1.00 0.00 SELECT tbl +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0x5796997451B1FA1D 1.0007 100.0% 1 1.0007 0.00 SELECT tbl diff --git a/t/lib/samples/QueryReportFormatter/report002.txt b/t/lib/samples/QueryReportFormatter/report002.txt index fbaedf8b..193d5acd 100644 --- a/t/lib/samples/QueryReportFormatter/report002.txt +++ b/t/lib/samples/QueryReportFormatter/report002.txt @@ -1,7 +1,6 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x3F79759E7FA2F117 at byte 1106 _____ -# Scores: Apdex = NS [0.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 09:23:49.637892 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -31,8 +30,7 @@ EXECUTE SELECT i FROM d.t WHERE i="3"\G SELECT i FROM d.t WHERE i="3"\G # Query 2: 0 QPS, 0x concurrency, ID 0xAA8E9FA785927259 at byte 0 ________ -# Scores: Apdex = NS [0.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 09:23:49.637394 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/lib/samples/QueryReportFormatter/report003.txt b/t/lib/samples/QueryReportFormatter/report003.txt index 9e92376b..c87a0881 100644 --- a/t/lib/samples/QueryReportFormatter/report003.txt +++ b/t/lib/samples/QueryReportFormatter/report003.txt @@ -1,12 +1,11 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x5796997451B1FA1D 1.0007 100.0% 1 1.0007 1.00 0.00 SELECT tbl +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0x5796997451B1FA1D 1.0007 100.0% 1 1.0007 0.00 SELECT tbl # Query 1: 0 QPS, 0x concurrency, ID 0x5796997451B1FA1D at byte 123 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/lib/samples/QueryReportFormatter/report004.txt b/t/lib/samples/QueryReportFormatter/report004.txt index 39e50b90..fadc6838 100644 --- a/t/lib/samples/QueryReportFormatter/report004.txt +++ b/t/lib/samples/QueryReportFormatter/report004.txt @@ -1,6 +1,6 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAECF4CA2310AC9E2 1.0303 97.1% 1 1.0303 NS 0.00 UPDATE foo -# MISC 0xMISC 0.0306 2.9% 2 0.0153 NS 0.0 <2 ITEMS> +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAECF4CA2310AC9E2 1.0303 97.1% 1 1.0303 0.00 UPDATE foo +# MISC 0xMISC 0.0306 2.9% 2 0.0153 0.0 <2 ITEMS> diff --git a/t/lib/samples/QueryReportFormatter/report005.txt b/t/lib/samples/QueryReportFormatter/report005.txt index aea3787c..502c32b9 100644 --- a/t/lib/samples/QueryReportFormatter/report005.txt +++ b/t/lib/samples/QueryReportFormatter/report005.txt @@ -1,5 +1,5 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============== ===== ====== ==== ===== ======== -# 1 0xCB5621E548E5497F 17.5000 100.0% 4 4.3750 NS 2.23 SELECT t +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============== ===== ====== ===== ======== +# 1 0xCB5621E548E5497F 17.5000 100.0% 4 4.3750 2.23 SELECT t diff --git a/t/lib/samples/QueryReportFormatter/report007.txt b/t/lib/samples/QueryReportFormatter/report007.txt index 3ce434fa..932ec60c 100644 --- a/t/lib/samples/QueryReportFormatter/report007.txt +++ b/t/lib/samples/QueryReportFormatter/report007.txt @@ -1,6 +1,6 @@ # Query 1: 2 QPS, 9.00x concurrency, ID 0x82860EDA9A88FCC5 at byte 1 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 5.44 +# Scores: V/M = 5.44 # Time range: 2007-10-15 21:43:52 to 21:43:53 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/lib/samples/QueryReportFormatter/report009.txt b/t/lib/samples/QueryReportFormatter/report009.txt index dcd22b37..e208c406 100644 --- a/t/lib/samples/QueryReportFormatter/report009.txt +++ b/t/lib/samples/QueryReportFormatter/report009.txt @@ -1,6 +1,6 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x5D51E5F01B88B79E at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-04-12 11:00:13.118191 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/lib/samples/QueryReportFormatter/report010.txt b/t/lib/samples/QueryReportFormatter/report010.txt index 6dcbd45c..319343f5 100644 --- a/t/lib/samples/QueryReportFormatter/report010.txt +++ b/t/lib/samples/QueryReportFormatter/report010.txt @@ -1,6 +1,6 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x82860EDA9A88FCC5 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = NS [0.0]*, V/M = 0.00 +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/lib/samples/QueryReportFormatter/report011.txt b/t/lib/samples/QueryReportFormatter/report011.txt index 42508fc8..02d54b0c 100644 --- a/t/lib/samples/QueryReportFormatter/report011.txt +++ b/t/lib/samples/QueryReportFormatter/report011.txt @@ -1,6 +1,6 @@ # Query 1: 0.67 QPS, 1x concurrency, ID 0x82860EDA9A88FCC5 at byte 0 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = NS [0.0]*, V/M = 0.33 +# Scores: V/M = 0.33 # Time range: 2007-10-15 21:43:52 to 21:43:55 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/lib/samples/QueryReportFormatter/report012.txt b/t/lib/samples/QueryReportFormatter/report012.txt index 31943a57..330f8d68 100644 --- a/t/lib/samples/QueryReportFormatter/report012.txt +++ b/t/lib/samples/QueryReportFormatter/report012.txt @@ -1,6 +1,6 @@ # Query 1: 1 QPS, 2x concurrency, ID 0x82860EDA9A88FCC5 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = NS [0.0]*, V/M = 0.30 +# Scores: V/M = 0.30 # Time range: 2007-10-15 21:43:52 to 21:43:55 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/lib/samples/QueryReportFormatter/report013.txt b/t/lib/samples/QueryReportFormatter/report013.txt index 1ef0919d..3ff99d58 100644 --- a/t/lib/samples/QueryReportFormatter/report013.txt +++ b/t/lib/samples/QueryReportFormatter/report013.txt @@ -1,5 +1,5 @@ # Item 1: 0 QPS, 0x concurrency, ID 0xEDEF654FCCC4A4D8 at byte 0 _________ -# Scores: Apdex = NS [0.0]*, V/M = 0.00 +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 100 2 diff --git a/t/lib/samples/QueryReportFormatter/report014.txt b/t/lib/samples/QueryReportFormatter/report014.txt index b0fc35ed..782b0010 100644 --- a/t/lib/samples/QueryReportFormatter/report014.txt +++ b/t/lib/samples/QueryReportFormatter/report014.txt @@ -1,5 +1,5 @@ # Item 1: 0 QPS, 0x concurrency, ID 0xEDEF654FCCC4A4D8 at byte 0 _________ -# Scores: Apdex = NS [0.0]*, V/M = 0.00 +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 100 3 diff --git a/t/lib/samples/QueryReportFormatter/report015.txt b/t/lib/samples/QueryReportFormatter/report015.txt index 04949587..382a228c 100644 --- a/t/lib/samples/QueryReportFormatter/report015.txt +++ b/t/lib/samples/QueryReportFormatter/report015.txt @@ -1,6 +1,5 @@ # Item 1: 0 QPS, 0x concurrency, ID 0xEDEF654FCCC4A4D8 at byte 0 _________ -# Scores: Apdex = NS [0.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 100 3 diff --git a/t/lib/samples/QueryReportFormatter/report016.txt b/t/lib/samples/QueryReportFormatter/report016.txt index b443426a..64434e38 100644 --- a/t/lib/samples/QueryReportFormatter/report016.txt +++ b/t/lib/samples/QueryReportFormatter/report016.txt @@ -1,6 +1,5 @@ # Item 1: 0 QPS, 0x concurrency, ID 0xEDEF654FCCC4A4D8 at byte 0 _________ -# Scores: Apdex = NS [0.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 100 1 diff --git a/t/lib/samples/QueryReportFormatter/report024.txt b/t/lib/samples/QueryReportFormatter/report024.txt index da2a0d3d..2b1b7d80 100644 --- a/t/lib/samples/QueryReportFormatter/report024.txt +++ b/t/lib/samples/QueryReportFormatter/report024.txt @@ -1,5 +1,5 @@ # Query 0: 0 QPS, 0x concurrency, ID 0x82860EDA9A88FCC5 at byte 0 ________ -# Scores: Apdex = NS [0.0]*, V/M = 0.00 +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/lib/samples/QueryReportFormatter/report027.txt b/t/lib/samples/QueryReportFormatter/report027.txt deleted file mode 100644 index fb3bc4ba..00000000 --- a/t/lib/samples/QueryReportFormatter/report027.txt +++ /dev/null @@ -1,58 +0,0 @@ - -# Profile -# Rank Query ID Response time Calls R/Call Apdx V/M EXPLAIN Item -# ==== ================== ============= ===== ====== ==== ===== ======= ========= -# 1 0x46F81B022F1AD76B 0.0003 100.0% 1 0.0003 NS 0.00 TF>aI SELECT t -# MISC 0xMISC 0.0003 100.0% 1 0.0003 NS 0.0 MISC <1 ITEMS> - -# Query 1: 0 QPS, 0x concurrency, ID 0x46F81B022F1AD76B at byte 0 ________ -# Scores: Apdex = NS [0.0]*, V/M = 0.00 -# EXPLAIN sparkline: TF>aI -# Query_time sparkline: | ^ | -# Time range: all events occurred at 2009-12-08 09:23:49.637394 -# Attribute pct total min max avg 95% stddev median -# ============ === ======= ======= ======= ======= ======= ======= ======= -# Count 100 1 -# Exec time 100 286us 286us 286us 286us 286us 0 286us -# Query size 100 90 90 90 90 90 0 90 -# String: -# cmd Query -# Databases qrf -# Query_time distribution -# 1us -# 10us -# 100us ################################################################ -# 1ms -# 10ms -# 100ms -# 1s -# 10s+ -# Tables -# SHOW TABLE STATUS FROM `qrf` LIKE 't'\G -# SHOW CREATE TABLE `qrf`.`t`\G -# EXPLAIN /*!50100 PARTITIONS*/ -select t1.i from t as t1 join t as t2 where t1.i < t2.i and t1.v is not null order by t1.i\G -# *************************** 1. row *************************** -# id: 1 -# select_type: SIMPLE -# table: t1 -# partitions: NULL -# type: ALL -# possible_keys: PRIMARY -# key: NULL -# key_len: NULL -# ref: NULL -# rows: 4 -# Extra: Using where; Using temporary; Using filesort -# *************************** 2. row *************************** -# id: 1 -# select_type: SIMPLE -# table: t2 -# partitions: NULL -# type: index -# possible_keys: PRIMARY -# key: PRIMARY -# key_len: 4 -# ref: NULL -# rows: 4 -# Extra: Using where; Using index; Using join buffer diff --git a/t/lib/samples/QueryReportFormatter/report028.txt b/t/lib/samples/QueryReportFormatter/report028.txt index 3640f6c1..eeba3c53 100644 --- a/t/lib/samples/QueryReportFormatter/report028.txt +++ b/t/lib/samples/QueryReportFormatter/report028.txt @@ -1,6 +1,6 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xFDE00DF974C61E9F at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.62 [1.0]*, V/M = 17.71 +# Scores: V/M = 17.71 # Query_time sparkline: |^^ ^^| # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/lib/samples/QueryReportFormatter/report029.txt b/t/lib/samples/QueryReportFormatter/report029.txt deleted file mode 100644 index 08605a95..00000000 --- a/t/lib/samples/QueryReportFormatter/report029.txt +++ /dev/null @@ -1,56 +0,0 @@ - -# Profile -# Rank Query ID Response time Calls R/Call Apdx V/M EXPLAIN Item -# ==== ================== ============= ===== ====== ==== ===== ======= ========= -# 1 0x46F81B022F1AD76B 0.0003 100.0% 1 0.0003 NS 0.00 TF>aI SELECT t -# MISC 0xMISC 0.0003 100.0% 1 0.0003 NS 0.0 MISC <1 ITEMS> - -# Query 1: 0 QPS, 0x concurrency, ID 0x46F81B022F1AD76B at byte 0 ________ -# Scores: Apdex = NS [0.0]*, V/M = 0.00 -# EXPLAIN sparkline: TF>aI -# Query_time sparkline: | ^ | -# Time range: all events occurred at 2009-12-08 09:23:49.637394 -# Attribute pct total min max avg 95% stddev median -# ============ === ======= ======= ======= ======= ======= ======= ======= -# Count 100 1 -# Exec time 100 286us 286us 286us 286us 286us 0 286us -# Query size 100 90 90 90 90 90 0 90 -# String: -# cmd Query -# Databases qrf -# Query_time distribution -# 1us -# 10us -# 100us ################################################################ -# 1ms -# 10ms -# 100ms -# 1s -# 10s+ -# Tables -# SHOW TABLE STATUS FROM `qrf` LIKE 't'\G -# SHOW CREATE TABLE `qrf`.`t`\G -# EXPLAIN /*!50100 PARTITIONS*/ -select t1.i from t as t1 join t as t2 where t1.i < t2.i and t1.v is not null order by t1.i\G -# *************************** 1. row *************************** -# id: 1 -# select_type: SIMPLE -# table: t1 -# type: ALL -# possible_keys: PRIMARY -# key: NULL -# key_len: NULL -# ref: NULL -# rows: 4 -# Extra: Using where; Using temporary; Using filesort -# *************************** 2. row *************************** -# id: 1 -# select_type: SIMPLE -# table: t2 -# type: index -# possible_keys: PRIMARY -# key: PRIMARY -# key_len: 4 -# ref: NULL -# rows: 4 -# Extra: Using where; Using index diff --git a/t/lib/samples/QueryReportFormatter/report032.txt b/t/lib/samples/QueryReportFormatter/report032.txt deleted file mode 100644 index d792a3b2..00000000 --- a/t/lib/samples/QueryReportFormatter/report032.txt +++ /dev/null @@ -1,58 +0,0 @@ - -# Profile -# Rank Query ID Response time Calls R/Call Apdx V/M EXPLAIN Item -# ==== ================== ============= ===== ====== ==== ===== ======= ========= -# 1 0x46F81B022F1AD76B 0.0003 100.0% 1 0.0003 NS 0.00 ia SELECT t -# MISC 0xMISC 0.0003 100.0% 1 0.0003 NS 0.0 MISC <1 ITEMS> - -# Query 1: 0 QPS, 0x concurrency, ID 0x46F81B022F1AD76B at byte 0 ________ -# Scores: Apdex = NS [0.0]*, V/M = 0.00 -# EXPLAIN sparkline: ia -# Query_time sparkline: | ^ | -# Time range: all events occurred at 2009-12-08 09:23:49.637394 -# Attribute pct total min max avg 95% stddev median -# ============ === ======= ======= ======= ======= ======= ======= ======= -# Count 100 1 -# Exec time 100 286us 286us 286us 286us 286us 0 286us -# Query size 100 90 90 90 90 90 0 90 -# String: -# cmd Query -# Databases qrf -# Query_time distribution -# 1us -# 10us -# 100us ################################################################ -# 1ms -# 10ms -# 100ms -# 1s -# 10s+ -# Tables -# SHOW TABLE STATUS FROM `qrf` LIKE 't'\G -# SHOW CREATE TABLE `qrf`.`t`\G -# EXPLAIN /*!50100 PARTITIONS*/ -select t1.i from t as t1 join t as t2 where t1.i < t2.i and t1.v is not null order by t1.i\G -# *************************** 1. row *************************** -# id: 1 -# select_type: SIMPLE -# table: t1 -# partitions: NULL -# type: index -# possible_keys: PRIMARY -# key: PRIMARY -# key_len: 4 -# ref: NULL -# rows: 4 -# Extra: Using where -# *************************** 2. row *************************** -# id: 1 -# select_type: SIMPLE -# table: t2 -# partitions: NULL -# type: ALL -# possible_keys: PRIMARY -# key: NULL -# key_len: NULL -# ref: NULL -# rows: 4 -# Extra: Range checked for each record (index map: 0x1) diff --git a/t/lib/samples/tcpdump/tcpdump042.txt b/t/lib/samples/tcpdump/tcpdump042.txt new file mode 100644 index 00000000..b91249e2 --- /dev/null +++ b/t/lib/samples/tcpdump/tcpdump042.txt @@ -0,0 +1,59 @@ +2013-01-24 12:55:38.276006 IP 127.0.0.1.62133 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0040 b290 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2b5 3039 58cf 8e7c 0000 0000 + 0x0020: b002 ffff fe34 0000 0204 3fd8 0103 0303 + 0x0030: 0101 080a 0580 fe1f 0000 0000 0402 0000 +2013-01-24 12:55:38.276053 IP 127.0.0.1.12345 > 127.0.0.1.62133: tcp 0 + 0x0000: 4500 0040 65de 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2b5 1c49 dad0 58cf 8e7d + 0x0020: b012 ffff fe34 0000 0204 3fd8 0103 0303 + 0x0030: 0101 080a 0580 fe1f 0580 fe1f 0402 0000 +2013-01-24 12:55:38.276062 IP 127.0.0.1.62133 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0034 2fb2 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2b5 3039 58cf 8e7d 1c49 dad1 + 0x0020: 8010 ffff fe28 0000 0101 080a 0580 fe1f + 0x0030: 0580 fe1f +2013-01-24 12:55:38.276071 IP 127.0.0.1.12345 > 127.0.0.1.62133: tcp 0 + 0x0000: 4500 0034 4cba 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2b5 1c49 dad1 58cf 8e7d + 0x0020: 8010 ffff fe28 0000 0101 080a 0580 fe1f + 0x0030: 0580 fe1f +2013-01-24 12:55:38.278813 IP 127.0.0.1.12345 > 127.0.0.1.62133: tcp 60 + 0x0000: 4508 0070 e5f9 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2b5 1c49 dad1 58cf 8e7d + 0x0020: 8018 ffff fe64 0000 0101 080a 0580 fe1f + 0x0030: 0580 fe1f 3800 0000 0a35 2e31 2e35 332d + 0x0040: 6c6f 6700 1800 0000 6553 5179 332d 2925 + 0x0050: 00ff f708 0200 0000 0000 0000 0000 0000 + 0x0060: 0000 007b 6154 5f62 4d3d 274a 2269 6900 +2013-01-24 12:55:38.278831 IP 127.0.0.1.62133 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0034 0cb3 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2b5 3039 58cf 8e7d 1c49 db0d + 0x0020: 8010 ffff fe28 0000 0101 080a 0580 fe1f + 0x0030: 0580 fe1f +2013-01-24 12:55:48.274417 IP 127.0.0.1.12345 > 127.0.0.1.62133: tcp 0 + 0x0000: 4508 0034 5ba9 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2b5 1c49 db0d 58cf 8e7d + 0x0020: 8011 ffff fe28 0000 0101 080a 0580 fe83 + 0x0030: 0580 fe1f +2013-01-24 12:55:48.274515 IP 127.0.0.1.62133 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0034 4493 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2b5 3039 58cf 8e7d 1c49 db0e + 0x0020: 8010 ffff fe28 0000 0101 080a 0580 fe83 + 0x0030: 0580 fe83 +2013-01-24 12:55:48.274541 IP 127.0.0.1.12345 > 127.0.0.1.62133: tcp 0 + 0x0000: 4508 0034 cfea 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2b5 1c49 db0e 58cf 8e7d + 0x0020: 8010 ffff fe28 0000 0101 080a 0580 fe83 + 0x0030: 0580 fe83 +2013-01-24 12:55:48.274741 IP 127.0.0.1.62133 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0034 6e98 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2b5 3039 58cf 8e7d 1c49 db0e + 0x0020: 8011 ffff fe28 0000 0101 080a 0580 fe83 + 0x0030: 0580 fe83 +2013-01-24 12:55:48.274836 IP 127.0.0.1.12345 > 127.0.0.1.62133: tcp 0 + 0x0000: 4508 0034 bcc4 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2b5 1c49 db0e 58cf 8e7e + 0x0020: 8010 fffe fe28 0000 0101 080a 0580 fe83 + 0x0030: 0580 fe83 + diff --git a/t/lib/samples/tcpdump/tcpdump043.txt b/t/lib/samples/tcpdump/tcpdump043.txt new file mode 100644 index 00000000..b73e5f5c --- /dev/null +++ b/t/lib/samples/tcpdump/tcpdump043.txt @@ -0,0 +1,82 @@ +2013-01-24 13:03:25.136681 IP 127.0.0.1.62160 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0040 ea0e 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2d0 3039 ad71 3d49 0000 0000 + 0x0020: b002 ffff fe34 0000 0204 3fd8 0103 0303 + 0x0030: 0101 080a 0581 1055 0000 0000 0402 0000 +2013-01-24 13:03:25.136728 IP 127.0.0.1.12345 > 127.0.0.1.62160: tcp 0 + 0x0000: 4500 0040 dc6f 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2d0 7d01 6881 ad71 3d4a + 0x0020: b012 ffff fe34 0000 0204 3fd8 0103 0303 + 0x0030: 0101 080a 0581 1055 0581 1055 0402 0000 +2013-01-24 13:03:25.136737 IP 127.0.0.1.62160 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0034 0e53 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2d0 3039 ad71 3d4a 7d01 6882 + 0x0020: 8010 ffff fe28 0000 0101 080a 0581 1055 + 0x0030: 0581 1055 +2013-01-24 13:03:25.136746 IP 127.0.0.1.12345 > 127.0.0.1.62160: tcp 0 + 0x0000: 4500 0034 f54e 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2d0 7d01 6882 ad71 3d4a + 0x0020: 8010 ffff fe28 0000 0101 080a 0581 1055 + 0x0030: 0581 1055 +2013-01-24 13:03:25.146062 IP 127.0.0.1.12345 > 127.0.0.1.62160: tcp 60 + 0x0000: 4508 0070 6334 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2d0 7d01 6882 ad71 3d4a + 0x0020: 8018 ffff fe64 0000 0101 080a 0581 1055 + 0x0030: 0581 1055 3800 0000 0a35 2e31 2e35 332d + 0x0040: 6c6f 6700 1b00 0000 4d34 5946 3267 3260 + 0x0050: 00ff f708 0200 0000 0000 0000 0000 0000 + 0x0060: 0000 006c 225e 3633 3a6c 3048 5863 6800 +2013-01-24 13:03:25.146080 IP 127.0.0.1.62160 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0034 3e79 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2d0 3039 ad71 3d4a 7d01 68be + 0x0020: 8010 ffff fe28 0000 0101 080a 0581 1055 + 0x0030: 0581 1055 +2013-01-24 13:03:28.672802 IP 127.0.0.1.62160 > 127.0.0.1.12345: tcp 15 + 0x0000: 4510 0043 145a 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2d0 3039 ad71 3d4a 7d01 68be + 0x0020: 8018 ffff fe37 0000 0101 080a 0581 1079 + 0x0030: 0581 1055 6865 6c6c 6f2c 2077 6f72 6c64 + 0x0040: 210d 0a +2013-01-24 13:03:28.672856 IP 127.0.0.1.12345 > 127.0.0.1.62160: tcp 0 + 0x0000: 4508 0034 b07b 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2d0 7d01 68be ad71 3d59 + 0x0020: 8010 ffff fe28 0000 0101 080a 0581 1079 + 0x0030: 0581 1079 +2013-01-24 13:03:28.672987 IP 127.0.0.1.12345 > 127.0.0.1.62160: tcp 31 + 0x0000: 4508 0053 6336 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2d0 7d01 68be ad71 3d59 + 0x0020: 8018 ffff fe47 0000 0101 080a 0581 1079 + 0x0030: 0581 1079 1b00 0001 ff84 0447 6f74 2070 + 0x0040: 6163 6b65 7473 206f 7574 206f 6620 6f72 + 0x0050: 6465 72 +2013-01-24 13:03:28.673017 IP 127.0.0.1.62160 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0034 fb76 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2d0 3039 ad71 3d59 7d01 68dd + 0x0020: 8010 ffff fe28 0000 0101 080a 0581 1079 + 0x0030: 0581 1079 +2013-01-24 13:03:28.673103 IP 127.0.0.1.12345 > 127.0.0.1.62160: tcp 0 + 0x0000: 4508 0034 ae21 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2d0 7d01 68dd ad71 3d59 + 0x0020: 8011 ffff fe28 0000 0101 080a 0581 1079 + 0x0030: 0581 1079 +2013-01-24 13:03:28.673139 IP 127.0.0.1.62160 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0034 d821 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2d0 3039 ad71 3d59 7d01 68de + 0x0020: 8010 ffff fe28 0000 0101 080a 0581 1079 + 0x0030: 0581 1079 +2013-01-24 13:03:28.673156 IP 127.0.0.1.12345 > 127.0.0.1.62160: tcp 0 + 0x0000: 4508 0034 ab2e 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2d0 7d01 68de ad71 3d59 + 0x0020: 8010 ffff fe28 0000 0101 080a 0581 1079 + 0x0030: 0581 1079 +2013-01-24 13:03:28.673444 IP 127.0.0.1.62160 > 127.0.0.1.12345: tcp 0 + 0x0000: 4510 0034 e03d 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 f2d0 3039 ad71 3d59 7d01 68de + 0x0020: 8011 ffff fe28 0000 0101 080a 0581 1079 + 0x0030: 0581 1079 +2013-01-24 13:03:28.673464 IP 127.0.0.1.12345 > 127.0.0.1.62160: tcp 0 + 0x0000: 4508 0034 b22d 4000 4006 0000 7f00 0001 + 0x0010: 7f00 0001 3039 f2d0 7d01 68de ad71 3d5a + 0x0020: 8010 fffe fe28 0000 0101 080a 0581 1079 + 0x0030: 0581 1079 + diff --git a/t/lib/samples/tcpdump/tcpdump044.txt b/t/lib/samples/tcpdump/tcpdump044.txt new file mode 100644 index 00000000..4a9b48ac --- /dev/null +++ b/t/lib/samples/tcpdump/tcpdump044.txt @@ -0,0 +1,70 @@ +2013-01-22 09:55:53.973868 IP 100.0.0.2.44432 > 100.0.0.1.3306: tcp 0 + 0x0000: 4510 003c bbae 4000 4006 f033 0a1c bd48 + 0x0010: 0a1c bd49 ad90 0cea af89 ab81 0000 0000 + 0x0020: a002 16d0 f7a5 0000 0204 05b4 0402 080a + 0x0030: 850b 102f 0000 0000 0103 0307 +2013-01-22 09:55:53.973885 IP 100.0.0.1.3306 > 100.0.0.2.44432: tcp 0 + 0x0000: 4500 003c 0000 4000 4006 abf2 0a1c bd49 + 0x0010: 0a1c bd48 0cea ad90 bcdd 5ddd af89 ab82 + 0x0020: a012 16a0 e720 0000 0204 05b4 0402 080a + 0x0030: 7a96 7b52 850b 102f 0103 0307 +2013-01-22 09:55:53.973886 IP 100.0.0.1.3306 > 100.0.0.2.44432: tcp 0 + 0x0000: 4500 003c 0000 4000 4006 abf2 0a1c bd49 + 0x0010: 0a1c bd48 0cea ad90 bcdd 5ddd af89 ab82 + 0x0020: a012 16a0 e720 0000 0204 05b4 0402 080a + 0x0030: 7a96 7b52 850b 102f 0103 0307 +2013-01-22 09:55:53.973929 IP 100.0.0.2.44432 > 100.0.0.1.3306: tcp 0 + 0x0000: 4510 0034 bbaf 4000 4006 f03a 0a1c bd48 + 0x0010: 0a1c bd49 ad90 0cea af89 ab82 bcdd 5dde + 0x0020: 8010 002e 2c5f 0000 0101 080a 850b 102f + 0x0030: 7a96 7b52 +2013-01-22 09:55:53.974017 IP 100.0.0.1.3306 > 100.0.0.2.44432: tcp 113 + 0x0000: 4508 00a5 268c 4000 4006 84f5 0a1c bd49 + 0x0010: 0a1c bd48 0cea ad90 bcdd 5dde af89 ab82 + 0x0020: 8018 002e 8f61 0000 0101 080a 7a96 7b52 + 0x0030: 850b 102f 6d00 0000 0a35 2e35 2e32 382d + 0x0040: 656e 7465 7270 7269 7365 2d63 6f6d 6d65 + 0x0050: 7263 6961 6c2d 6164 7661 6e63 6564 2d6c + 0x0060: 6f67 000d 0000 006c 706d 5338 5d4a 3c00 + 0x0070: fff7 0802 000f 8015 0000 0000 0000 0000 + 0x0080: 0000 2f72 7265 247e 7347 4565 4f3c 006d + 0x0090: 7973 716c 5f6e 6174 6976 655f 7061 7373 + 0x00a0: 776f 7264 00 +2013-01-22 09:55:53.974019 IP 100.0.0.1.3306 > 100.0.0.2.44432: tcp 113 + 0x0000: 4508 00a5 268c 4000 4006 84f5 0a1c bd49 + 0x0010: 0a1c bd48 0cea ad90 bcdd 5dde af89 ab82 + 0x0020: 8018 002e 8f61 0000 0101 080a 7a96 7b52 + 0x0030: 850b 102f 6d00 0000 0a35 2e35 2e32 382d + 0x0040: 656e 7465 7270 7269 7365 2d63 6f6d 6d65 + 0x0050: 7263 6961 6c2d 6164 7661 6e63 6564 2d6c + 0x0060: 6f67 000d 0000 006c 706d 5338 5d4a 3c00 + 0x0070: fff7 0802 000f 8015 0000 0000 0000 0000 + 0x0080: 0000 2f72 7265 247e 7347 4565 4f3c 006d + 0x0090: 7973 716c 5f6e 6174 6976 655f 7061 7373 + 0x00a0: 776f 7264 00 +2013-01-22 09:55:53.974064 IP 100.0.0.2.44432 > 100.0.0.1.3306: tcp 0 + 0x0000: 4510 0034 bbb0 4000 4006 f039 0a1c bd48 + 0x0010: 0a1c bd49 ad90 0cea af89 ab82 bcdd 5e4f + 0x0020: 8010 002e 2bee 0000 0101 080a 850b 102f + 0x0030: 7a96 7b52 +2013-01-22 09:55:57.793375 IP 100.0.0.2.44432 > 100.0.0.1.3306: tcp 0 + 0x0000: 4510 0034 bbb1 4000 4006 f038 0a1c bd48 + 0x0010: 0a1c bd49 ad90 0cea af89 ab82 bcdd 5e4f + 0x0020: 8011 002e 1d02 0000 0101 080a 850b 1f1a + 0x0030: 7a96 7b52 +2013-01-22 09:55:57.793485 IP 100.0.0.1.3306 > 100.0.0.2.44432: tcp 0 + 0x0000: 4508 0034 268d 4000 4006 8565 0a1c bd49 + 0x0010: 0a1c bd48 0cea ad90 bcdd 5e4f af89 ab83 + 0x0020: 8011 002e 0e16 0000 0101 080a 7a96 8a3d + 0x0030: 850b 1f1a +2013-01-22 09:55:57.793489 IP 100.0.0.1.3306 > 100.0.0.2.44432: tcp 0 + 0x0000: 4508 0034 268d 4000 4006 8565 0a1c bd49 + 0x0010: 0a1c bd48 0cea ad90 bcdd 5e4f af89 ab83 + 0x0020: 8011 002e 0e16 0000 0101 080a 7a96 8a3d + 0x0030: 850b 1f1a +2013-01-22 09:55:57.793529 IP 100.0.0.2.44432 > 100.0.0.1.3306: tcp 0 + 0x0000: 4510 0034 bbb2 4000 4006 f037 0a1c bd48 + 0x0010: 0a1c bd49 ad90 0cea af89 ab83 bcdd 5e50 + 0x0020: 8010 002e 0e15 0000 0101 080a 850b 1f1b + 0x0030: 7a96 8a3d + diff --git a/t/pt-archiver/file.t b/t/pt-archiver/file.t index 928e4d2d..121ca890 100644 --- a/t/pt-archiver/file.t +++ b/t/pt-archiver/file.t @@ -118,6 +118,7 @@ like( # ############################################################################# # Done. # ############################################################################# +diag(`rm -f /tmp/*.table_1`); $sb->wipe_clean($dbh); ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); diff --git a/t/pt-heartbeat/bugs.t b/t/pt-heartbeat/bugs.t index d50ef976..0cff266a 100644 --- a/t/pt-heartbeat/bugs.t +++ b/t/pt-heartbeat/bugs.t @@ -93,7 +93,7 @@ my $slave1_dsn = $sb->dsn_for('slave1'); local $ENV{TZ} = '-09:00'; tzset(); pt_heartbeat::main($slave1_dsn, qw(--database test --table heartbeat), - qw(--check --master-server-id), $master_port) + qw(--utc --check --master-server-id), $master_port) }); # If the servers use UTC then the lag should be 0.00, or at least @@ -102,11 +102,35 @@ my $slave1_dsn = $sb->dsn_for('slave1'); like( $output, qr/\A\d.\d{2}$/, - "Bug 886059: pt-heartbeat doesn't get confused with differing timezones" + "--utc bypasses time zone differences (bug 886059, bug 1099665)" ); stop_all_instances(); +# ############################################################################# +# pt-heartbeat 2.1.8 doesn't use precision/sub-second timestamps +# https://bugs.launchpad.net/percona-toolkit/+bug/1103221 +# ############################################################################# + +$master_dbh->do('truncate table test.heartbeat'); +$sb->wait_for_slaves; + +my $master_dsn = $sb->dsn_for('master'); + +($output) = output( + sub { + pt_heartbeat::main($master_dsn, qw(--database test --update), + qw(--run-time 1)) + }, +); + +my ($row) = $master_dbh->selectrow_hashref('select * from test.heartbeat'); +like( + $row->{ts}, + qr/\d{4}-\d\d-\d\dT\d+:\d+:\d+\.\d+/, + "Hi-res timestamp (bug 1103221)" +); + # ############################################################################ # Done. # ############################################################################ diff --git a/t/pt-online-schema-change/bugs.t b/t/pt-online-schema-change/bugs.t index 58b1b567..16fce594 100644 --- a/t/pt-online-schema-change/bugs.t +++ b/t/pt-online-schema-change/bugs.t @@ -210,7 +210,7 @@ $sb->load_file('master', "$sample/del-trg-bug-1062324.sql"); sub { pt_online_schema_change::main(@args, "$master_dsn,D=test,t=t1", "--alter", "drop key 2bpk, drop key c3, drop primary key, drop c1, add primary key (c2, c3(4)), add key (c3(4))", - qw(--execute --no-drop-new-table --no-swap-tables)) }, + qw(--no-check-alter --execute --no-drop-new-table --no-swap-tables)) }, ); # Since _t1_new no longer has the c1 column, the bug caused this @@ -233,6 +233,34 @@ $sb->load_file('master', "$sample/del-trg-bug-1062324.sql"); undef, "Delete trigger works after altering PK (bug 1062324)" ); + + # Another instance of this bug: + # https://bugs.launchpad.net/percona-toolkit/+bug/1103672 + $sb->load_file('master', "$sample/del-trg-bug-1103672.sql"); + + ($output, $exit_status) = full_output( + sub { pt_online_schema_change::main(@args, + "$master_dsn,D=test,t=t1", + "--alter", "drop primary key, add column _id int unsigned not null primary key auto_increment FIRST", + qw(--no-check-alter --execute --no-drop-new-table --no-swap-tables)) }, + ); + + eval { + $master_dbh->do("DELETE FROM test.t1 WHERE id=1"); + }; + is( + $EVAL_ERROR, + "", + "No delete trigger error after altering PK (bug 1103672)" + ) or diag($output); + + $row = $master_dbh->selectrow_arrayref("SELECT * FROM test._t1_new WHERE id=1"); + is( + $row, + undef, + "Delete trigger works after altering PK (bug 1103672)" + ); + } # ############################################################################# diff --git a/t/pt-online-schema-change/check_alter.t b/t/pt-online-schema-change/check_alter.t new file mode 100644 index 00000000..7afd3c97 --- /dev/null +++ b/t/pt-online-schema-change/check_alter.t @@ -0,0 +1,65 @@ +#!/usr/bin/env perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +use Data::Dumper; +use PerconaTest; +use Sandbox; + +require "$trunk/bin/pt-online-schema-change"; + +my $dp = new DSNParser(opts=>$dsn_opts); +my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); +my $master_dbh = $sb->get_dbh_for('master'); +my $slave_dbh = $sb->get_dbh_for('slave1'); + +if ( !$master_dbh ) { + plan skip_all => 'Cannot connect to sandbox master'; +} +elsif ( !$slave_dbh ) { + plan skip_all => 'Cannot connect to sandbox slave1'; +} + +# The sandbox servers run with lock_wait_timeout=3 and it's not dynamic +# so we need to specify --lock-wait-timeout=3 else the tool will die. +my $master_dsn = 'h=127.1,P=12345,u=msandbox,p=msandbox'; +my @args = (qw(--lock-wait-timeout 3)); +my $output; +my $exit_status; +my $sample = "t/pt-online-schema-change/samples/"; + +# ############################################################################# +# DROP PRIMARY KEY +# ############################################################################# + +$sb->load_file('master', "$sample/del-trg-bug-1103672.sql"); + +($output, $exit_status) = full_output( + sub { pt_online_schema_change::main(@args, + "$master_dsn,D=test,t=t1", + "--alter", "drop primary key, add column _id int unsigned not null primary key auto_increment FIRST", + qw(--execute)), + }, +); + +like( + $output, + qr/--check-alter failed/, + "DROP PRIMARY KEY" +); + +# ############################################################################# +# Done. +# ############################################################################# +$sb->wipe_clean($master_dbh); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +done_testing; diff --git a/t/pt-online-schema-change/samples/del-trg-bug-1103672.sql b/t/pt-online-schema-change/samples/del-trg-bug-1103672.sql new file mode 100644 index 00000000..a5d7699e --- /dev/null +++ b/t/pt-online-schema-change/samples/del-trg-bug-1103672.sql @@ -0,0 +1,20 @@ +drop database if exists test; +create database test; +use test; + +CREATE TABLE `t1` ( + `id` int(10) unsigned NOT NULL, + `x` char(3) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB; + +INSERT INTO t1 VALUES + (1, 'a'), + (2, 'b'), + (3, 'c'), + (4, 'd'), + (5, 'f'), + (6, 'g'), + (7, 'h'), + (8, 'i'), + (9, 'j'); diff --git a/t/pt-pmp/aggregate_stacktrace.sh b/t/pt-pmp/aggregate_stacktrace.sh deleted file mode 100644 index 62dbb549..00000000 --- a/t/pt-pmp/aggregate_stacktrace.sh +++ /dev/null @@ -1,123 +0,0 @@ -#!/usr/bin/env bash - -# This test file must be ran by util/test-bash-functions. - -TESTS=6 -PT_TMPDIR=$TEST_PT_TMPDIR - -# ############################################################################ -TEST_NAME="stacktrace-001.txt" -# ############################################################################ -cat > $PT_TMPDIR/expected < $PT_TMPDIR/got -no_diff $PT_TMPDIR/got $PT_TMPDIR/expected - -# ############################################################################ -TEST_NAME="stacktrace-002.txt" -# ############################################################################ -cat > $PT_TMPDIR/expected < $PT_TMPDIR/got -no_diff $PT_TMPDIR/got $PT_TMPDIR/expected - -# ############################################################################ -TEST_NAME="stacktrace-003.txt" -# ############################################################################ -cat > $PT_TMPDIR/expected < $PT_TMPDIR/got -no_diff $PT_TMPDIR/got $PT_TMPDIR/expected - -# ############################################################################ -TEST_NAME="stacktrace-003-b.txt" -# ############################################################################ -cat > $PT_TMPDIR/expected < $PT_TMPDIR/got -no_diff $PT_TMPDIR/got $PT_TMPDIR/expected - -# ############################################################################ -TEST_NAME="stacktrace-004.txt" -# ############################################################################ -cat > $PT_TMPDIR/expected < $PT_TMPDIR/got -no_diff $PT_TMPDIR/got $PT_TMPDIR/expected - -# ############################################################################ -TEST_NAME="stacktrace-005.txt" -# ############################################################################ -cat > $PT_TMPDIR/expected < $PT_TMPDIR/got -no_diff $PT_TMPDIR/got $PT_TMPDIR/expected diff --git a/t/pt-pmp/pt-pmp.t b/t/pt-pmp/pt-pmp.t index 4d3f85ea..378e6309 100644 --- a/t/pt-pmp/pt-pmp.t +++ b/t/pt-pmp/pt-pmp.t @@ -11,9 +11,30 @@ use warnings FATAL => 'all'; use English qw(-no_match_vars); use PerconaTest; +use Test::More; -my ($tool) = $PROGRAM_NAME =~ m/([\w-]+)\.t$/; -push @ARGV, "$trunk/t/$tool/*.sh" unless @ARGV; -system("$trunk/util/test-bash-functions $trunk/bin/$tool @ARGV"); +my $sample = "$trunk/t/pt-pmp/samples"; -exit; +opendir my $dh, $sample or die "Error opening $sample: $OS_ERROR"; +while ( my $file = readdir $dh ) { + next unless -f "$sample/$file" && "$sample/$file" =~ m/\.in$/; + (my $outfile = $file) =~ s/\.in/.out/; + ok( + no_diff( + "$trunk/bin/pt-pmp $sample/$file", + "t/pt-pmp/samples/$outfile", + ), + "$file" + ); +} +closedir $dh; + +ok( + no_diff( + "$trunk/bin/pt-pmp -l 2 $sample/stacktrace003.in", + "t/pt-pmp/samples/stacktrace003-limit2.out", + ), + "Limit 2 (stacktrace003-limit2.out)" +); + +done_testing; diff --git a/t/pt-pmp/samples/stacktrace-001.txt b/t/pt-pmp/samples/stacktrace001.in similarity index 100% rename from t/pt-pmp/samples/stacktrace-001.txt rename to t/pt-pmp/samples/stacktrace001.in diff --git a/t/pt-pmp/samples/stacktrace001.out b/t/pt-pmp/samples/stacktrace001.out new file mode 100644 index 00000000..c45192b8 --- /dev/null +++ b/t/pt-pmp/samples/stacktrace001.out @@ -0,0 +1,20 @@ + 187 __lll_mutex_lock_wait(libpthread.so.0),_L_mutex_lock_1133(libpthread.so.0),pthread_mutex_lock(libpthread.so.0),safe_mutex_lock,open_table,open_tables,open_and_lock_tables,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 62 __lll_mutex_lock_wait(libpthread.so.0),_L_mutex_lock_1133(libpthread.so.0),pthread_mutex_lock(libpthread.so.0),safe_mutex_lock,close_thread_tables,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 39 read(libpthread.so.0),vio_read(unistd.h:35),my_real_read,my_net_read,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 18 pthread_cond_wait,safe_cond_wait,os_event_wait_low,os_aio_simulated_handle,fil_aio_wait,io_handler_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 15 pthread_cond_wait,safe_cond_wait,end_thread,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 15 __lll_mutex_lock_wait(libpthread.so.0),_L_mutex_lock_1133(libpthread.so.0),pthread_mutex_lock(libpthread.so.0),safe_mutex_lock,open_table,open_tables,mysql_update,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 12 __lll_mutex_lock_wait(libpthread.so.0),_L_mutex_lock_1133(libpthread.so.0),pthread_mutex_lock(libpthread.so.0),safe_mutex_lock,open_table,open_tables,open_and_lock_tables,mysql_insert,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 2 __lll_mutex_lock_wait(libpthread.so.0),_L_mutex_lock_107(libpthread.so.0),pthread_mutex_lock(libpthread.so.0),safe_mutex_lock,Log_event::read_log_event,mysql_binlog_send,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),os_thread_sleep,srv_master_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),os_thread_sleep,srv_lock_timeout_and_monitor_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),os_thread_sleep,srv_error_monitor_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),handle_connections_sockets,main + 1 _sanity,_myfree,st_join_table::cleanup,JOIN::cleanup,JOIN::join_free,do_select,JOIN::exec,mysql_select,handle_select,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 pread64(libpthread.so.0),_os_file_pread(unistd.h:57),_os_file_read,_fil_io,buf_read_page_low,buf_read_page,buf_page_get_gen,btr_cur_search_to_nth_level,btr_estimate_n_rows_in_range,ha_innobase::records_in_range,check_quick_keys,check_quick_select,get_key_scans_params,SQL_SELECT::test_quick_select,mysql_update,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 __lll_mutex_lock_wait(libpthread.so.0),_L_mutex_lock_1133(libpthread.so.0),pthread_mutex_lock(libpthread.so.0),safe_mutex_lock,_sanity,_myrealloc,String::realloc,String::append,Log_event::read_log_event,mysql_binlog_send,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 __lll_mutex_lock_wait(libpthread.so.0),_L_mutex_lock_1133(libpthread.so.0),pthread_mutex_lock(libpthread.so.0),safe_mutex_lock,_sanity,_mymalloc,_myrealloc,mi_alloc_rec_buff,mi_open,ha_myisam::open,handler::ha_open,open_tmp_table,create_tmp_table,select_union::create_result_table,mysql_derived_prepare,mysql_handle_derived,open_and_lock_tables,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 __lll_mutex_lock_wait(libpthread.so.0),_L_mutex_lock_1133(libpthread.so.0),pthread_mutex_lock(libpthread.so.0),safe_mutex_lock,_sanity,_mymalloc,init_dynamic_array,QUICK_RANGE_SELECT,get_quick_select,TRP_RANGE::make_quick,SQL_SELECT::test_quick_select,make_join_statistics,JOIN::optimize,mysql_select,mysql_derived_filling,mysql_handle_derived,open_and_lock_tables,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 __lll_mutex_lock_wait(libpthread.so.0),_L_mutex_lock_1133(libpthread.so.0),pthread_mutex_lock(libpthread.so.0),safe_mutex_lock,_mymalloc,alloc_root,MYSQLparse,mysql_make_view,open_unireg_entry,open_table,open_tables,open_and_lock_tables,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 __lll_mutex_lock_wait(libpthread.so.0),_L_mutex_lock_107(libpthread.so.0),pthread_mutex_lock(libpthread.so.0),safe_mutex_lock,mi_open,ha_myisam::open,handler::ha_open,open_tmp_table,create_tmp_table,select_union::create_result_table,mysql_derived_prepare,mysql_handle_derived,open_and_lock_tables,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 do_sigwait(libpthread.so.0),sigwait(libpthread.so.0),signal_hand,start_thread(libpthread.so.0),clone(libc.so.6) diff --git a/t/pt-pmp/samples/stacktrace-002.txt b/t/pt-pmp/samples/stacktrace002.in similarity index 100% rename from t/pt-pmp/samples/stacktrace-002.txt rename to t/pt-pmp/samples/stacktrace002.in diff --git a/t/pt-pmp/samples/stacktrace002.out b/t/pt-pmp/samples/stacktrace002.out new file mode 100644 index 00000000..d3e181bb --- /dev/null +++ b/t/pt-pmp/samples/stacktrace002.out @@ -0,0 +1,12 @@ + 2387 pthread_cond_wait,open_table,open_tables,open_and_lock_tables_derived,execute_sqlcom_select,mysql_execute_command,mysql_parse,dispatch_command,do_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 5 pthread_cond_wait,open_table,open_tables,open_and_lock_tables_derived,mysql_insert,mysql_execute_command,mysql_parse,dispatch_command,do_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 4 pthread_cond_wait,os_event_wait_low,os_aio_simulated_handle,fil_aio_wait,io_handler_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 4 pthread_cond_wait,open_table,open_tables,open_and_lock_tables_derived,mysql_delete,mysql_execute_command,mysql_parse,dispatch_command,do_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),os_thread_sleep,srv_master_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),os_thread_sleep,srv_lock_timeout_and_monitor_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),os_thread_sleep,srv_error_monitor_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),handle_connections_sockets,main,select(libc.so.6) + 1 read(libpthread.so.0),my_real_read,my_net_read,do_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 pthread_cond_wait,cache_thread,one_thread_per_connection_end,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 free(libc.so.6),ut_free,page_cur_insert_rec_low,btr_cur_optimistic_insert,row_ins_index_entry_low,row_ins_index_entry,row_ins,row_ins_step,row_insert_for_mysql,ha_innobase::write_row,handler::ha_write_row,ha_partition::copy_partitions,ha_partition::change_partitions,handler::ha_change_partitions,mysql_change_partitions,fast_alter_partition_table,mysql_alter_table,mysql_execute_command,mysql_parse,dispatch_command,do_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 do_sigwait(libpthread.so.0),sigwait(libpthread.so.0),signal_hand,start_thread(libpthread.so.0),clone(libc.so.6) diff --git a/t/pt-pmp/samples/stacktrace003-limit2.out b/t/pt-pmp/samples/stacktrace003-limit2.out new file mode 100644 index 00000000..1782bb88 --- /dev/null +++ b/t/pt-pmp/samples/stacktrace003-limit2.out @@ -0,0 +1,9 @@ + 35 pthread_cond_wait,end_thread + 20 read(libpthread.so.0),read(unistd.h:35) + 18 pthread_cond_wait,os_event_wait_low + 3 select(libc.so.6),os_thread_sleep + 3 pthread_cond_wait,MYSQL_LOG::wait_for_update + 1 select(libc.so.6),handle_connections_sockets + 1 do_sigwait(libpthread.so.0),sigwait(libpthread.so.0) + 1 btr_search_guess_on_hash(libc.so.6),btr_cur_search_to_nth_level + 1 btr_cur_search_to_nth_level,btr_estimate_n_rows_in_range diff --git a/t/pt-pmp/samples/stacktrace-003.txt b/t/pt-pmp/samples/stacktrace003.in similarity index 100% rename from t/pt-pmp/samples/stacktrace-003.txt rename to t/pt-pmp/samples/stacktrace003.in diff --git a/t/pt-pmp/samples/stacktrace003.out b/t/pt-pmp/samples/stacktrace003.out new file mode 100644 index 00000000..3035b521 --- /dev/null +++ b/t/pt-pmp/samples/stacktrace003.out @@ -0,0 +1,11 @@ + 35 pthread_cond_wait,end_thread,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 20 read(libpthread.so.0),read(unistd.h:35),vio_read(unistd.h:35),my_real_read,my_net_read,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 18 pthread_cond_wait,os_event_wait_low,os_aio_simulated_handle,fil_aio_wait,io_handler_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 3 pthread_cond_wait,MYSQL_LOG::wait_for_update,mysql_binlog_send,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),os_thread_sleep,srv_master_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),os_thread_sleep,srv_lock_timeout_and_monitor_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),os_thread_sleep,srv_error_monitor_thread,start_thread(libpthread.so.0),clone(libc.so.6) + 1 select(libc.so.6),handle_connections_sockets,main + 1 do_sigwait(libpthread.so.0),sigwait(libpthread.so.0),signal_hand,start_thread(libpthread.so.0),clone(libc.so.6) + 1 btr_search_guess_on_hash(libc.so.6),btr_cur_search_to_nth_level,btr_pcur_open_with_no_init,row_search_for_mysql,ha_innobase::index_read,join_read_always_key,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,evaluate_join_record,sub_select,do_select,JOIN::exec,mysql_select,handle_select,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) + 1 btr_cur_search_to_nth_level,btr_estimate_n_rows_in_range,ha_innobase::records_in_range,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_keys,check_quick_select,get_key_scans_params,SQL_SELECT::test_quick_select,get_quick_record_count,make_join_statistics,JOIN::optimize,mysql_select,handle_select,mysql_execute_command,mysql_parse,dispatch_command,handle_one_connection,start_thread(libpthread.so.0),clone(libc.so.6) diff --git a/t/pt-pmp/samples/stacktrace-004.txt b/t/pt-pmp/samples/stacktrace004.in similarity index 100% rename from t/pt-pmp/samples/stacktrace-004.txt rename to t/pt-pmp/samples/stacktrace004.in diff --git a/t/pt-pmp/samples/stacktrace004.out b/t/pt-pmp/samples/stacktrace004.out new file mode 100644 index 00000000..e144a372 --- /dev/null +++ b/t/pt-pmp/samples/stacktrace004.out @@ -0,0 +1,5 @@ + 33 pthread_cond_wait,boost::condition_variable::wait,Queue::pop,Worker::work,boost::_mfi::mf0::operator,boost::_bi::list1::operator,boost::_bi::bind_t::operator,boost::detail::thread_data::run,thread_proxy(libboost_thread-mt.so.5),start_thread(libpthread.so.0),clone(libc.so.6),?? + 1 StringBuilder::length,Parser::add,Parser::try_parse_query,Parser::parse_block,Parser::work,boost::_mfi::mf0::operator,boost::_bi::list1::operator,boost::_bi::bind_t::operator,boost::detail::thread_data::run,thread_proxy(libboost_thread-mt.so.5),start_thread(libpthread.so.0),clone(libc.so.6),?? + 1 pthread_cond_wait,boost::thread::join(libboost_thread-mt.so.5),LogReader::wait,Replay::wait,main + 1 pthread_cond_wait,boost::condition_variable::wait,Queue::push,LogReader::work,boost::_mfi::mf0::operator,boost::_bi::list1::operator,boost::_bi::bind_t::operator,boost::detail::thread_data::run,thread_proxy(libboost_thread-mt.so.5),start_thread(libpthread.so.0),clone(libc.so.6),?? + 1 pthread_cond_wait,boost::condition_variable::wait,Queue::pop,Reporter::work,boost::_mfi::mf0::operator,boost::_bi::list1::operator,boost::_bi::bind_t::operator,boost::detail::thread_data::run,thread_proxy(libboost_thread-mt.so.5),start_thread(libpthread.so.0),clone(libc.so.6),?? diff --git a/t/pt-pmp/samples/stacktrace-005.txt b/t/pt-pmp/samples/stacktrace005.in similarity index 100% rename from t/pt-pmp/samples/stacktrace-005.txt rename to t/pt-pmp/samples/stacktrace005.in diff --git a/t/pt-pmp/samples/stacktrace005.out b/t/pt-pmp/samples/stacktrace005.out new file mode 100644 index 00000000..4b2e414c --- /dev/null +++ b/t/pt-pmp/samples/stacktrace005.out @@ -0,0 +1,6 @@ + 32 read(libc.so.6),vio_read_buff(libmysqlclient.so.16),libmysqlclient::??(libmysqlclient.so.16),my_net_read(libmysqlclient.so.16),cli_safe_read(libmysqlclient.so.16),libmysqlclient::??(libmysqlclient.so.16),mysql_real_query(libmysqlclient.so.16),Connection::run,Worker::work,thread_proxy(libboost_thread-mt.so.5),start_thread(libpthread.so.0),clone(libc.so.6),?? + 1 pthread_cond_wait,LogReader::work,thread_proxy(libboost_thread-mt.so.5),start_thread(libpthread.so.0),clone(libc.so.6),?? + 1 pthread_cond_wait,boost::thread::join(libboost_thread-mt.so.5),main + 1 pthread_cond_wait,boost::condition_variable::wait,Worker::work,thread_proxy(libboost_thread-mt.so.5),start_thread(libpthread.so.0),clone(libc.so.6),?? + 1 pthread_cond_wait,boost::condition_variable::wait,Reporter::work,thread_proxy(libboost_thread-mt.so.5),start_thread(libpthread.so.0),clone(libc.so.6),?? + 1 pthread_cond_wait,boost::condition_variable::wait,Queue::push,Parser::work,thread_proxy(libboost_thread-mt.so.5),start_thread(libpthread.so.0),clone(libc.so.6),?? diff --git a/t/pt-query-digest/execute.t b/t/pt-query-digest/execute.t deleted file mode 100644 index 75b51203..00000000 --- a/t/pt-query-digest/execute.t +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env perl - -BEGIN { - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; -}; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); -use Test::More; - -use Sandbox; -use PerconaTest; - -require "$trunk/bin/pt-query-digest"; - -my $dp = new DSNParser(opts=>$dsn_opts); -my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); -my $dbh = $sb->get_dbh_for('master'); - -if ( !$dbh ) { - plan skip_all => 'Cannot connect to sandbox master'; -} -else { - plan tests => 6; -} - -my $output = ''; -my $cnf = 'h=127.1,P=12345,u=msandbox,p=msandbox'; -my @args = qw(--report-format=query_report --limit 10 --stat); - -$sb->create_dbs($dbh, [qw(test)]); -$dbh->do('use test'); -$dbh->do('create table foo (a int, b int, c int)'); - -is_deeply( - $dbh->selectall_arrayref('select * from test.foo'), - [], - 'No rows in table yet' -); - -ok( - no_diff( - sub { pt_query_digest::main(@args, '--execute', $cnf, - "$trunk/t/lib/samples/slowlogs/slow018.txt") }, - 't/pt-query-digest/samples/slow018_execute_report_1.txt', - ), - '--execute without database' -); - -is_deeply( - $dbh->selectall_arrayref('select * from test.foo'), - [], - 'Still no rows in table' -); - -# Provide a default db to make --execute work. -$cnf .= ',D=test'; - -# TODO: This test is a PITA because every time the mqd output -# changes the -n of tail has to be adjusted. - -# - -# We tail to get everything from "Exec orig" onward. The lines -# above have the real execution time will will vary. The last 18 lines -# are sufficient to see that it actually executed without errors. -ok( - no_diff( - sub { pt_query_digest::main(@args, '--execute', $cnf, - "$trunk/t/lib/samples/slowlogs/slow018.txt") }, - 't/pt-query-digest/samples/slow018_execute_report_2.txt', - trf => 'tail -n 30', - sed => ["-e 's/s ##*/s/g'"], - ), - '--execute with default database' -); - -is_deeply( - $dbh->selectall_arrayref('select * from test.foo'), - [[qw(1 2 3)],[qw(4 5 6)]], - 'Rows in table' -); - -# ############################################################################# -# Done. -# ############################################################################# -$sb->wipe_clean($dbh); -ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); -exit; diff --git a/t/pt-query-digest/issue_360.t b/t/pt-query-digest/issue_360.t index 65069d3b..b3a1effc 100644 --- a/t/pt-query-digest/issue_360.t +++ b/t/pt-query-digest/issue_360.t @@ -34,11 +34,11 @@ else { my $pid_file = "/tmp/pt-query-digest-test-issue_360.t.$PID"; # Need a clean query review table. -$sb->create_dbs($dbh, [qw(test)]); +$sb->create_dbs($dbh, [qw(test percona_schema)]); # Run pt-query-digest in the background for 2s, # saving queries to test.query_review. -diag(`$trunk/bin/pt-query-digest --processlist h=127.1,P=12345,u=msandbox,p=msandbox --interval 0.01 --create-review-table --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=query_review --daemonize --pid $pid_file --log /dev/null --run-time 2`); +diag(`$trunk/bin/pt-query-digest --processlist h=127.1,P=12345,u=msandbox,p=msandbox --interval 0.01 --create-review-table --review h=127.1,P=12345,u=msandbox,p=msandbox --review-table test.query_review --daemonize --pid $pid_file --log /dev/null --run-time 2`); # Wait until its running. PerconaTest::wait_for_files($pid_file); diff --git a/t/pt-query-digest/mirror.t b/t/pt-query-digest/mirror.t deleted file mode 100644 index 27e77aae..00000000 --- a/t/pt-query-digest/mirror.t +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env perl - -BEGIN { - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; -}; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); -use Test::More; -use Time::HiRes qw(sleep); - -use PerconaTest; -use DSNParser; -use Sandbox; - -my $dp = new DSNParser(opts=>$dsn_opts); -my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); -my $dbh1 = $sb->get_dbh_for('master'); -my $dbh2 = $sb->get_dbh_for('slave1'); - -if ( !$dbh1 ) { - plan skip_all => 'Cannot connect to sandbox master'; -} -elsif ( !$dbh2 ) { - plan skip_all => 'Cannot connect to sandbox slave'; -} -else { - plan tests => 5; -} - -my $output; -my $cmd; -my $pid_file = "/tmp/pt-query-digest-mirror-test.pid"; -diag(`rm $pid_file 2>/dev/null`); - -# ########################################################################## -# Tests for swapping --processlist and --execute -# ########################################################################## -$dbh1->do('set global read_only=0'); -$dbh2->do('set global read_only=1'); -$cmd = "$trunk/bin/pt-query-digest " - . "--processlist h=127.1,P=12345,u=msandbox,p=msandbox " - . "--execute h=127.1,P=12346,u=msandbox,p=msandbox --mirror 1 " - . "--pid $pid_file"; - -{ - local $ENV{PTDEBUG}=1; - `$cmd > /tmp/read_only.txt 2>&1 &`; -} - -$dbh1->do('select sleep(1)'); -$dbh1->do('set global read_only=1'); -$dbh2->do('set global read_only=0'); -$dbh1->do('select sleep(1)'); - -PerconaTest::wait_for_files($pid_file); -chomp(my $pid = `cat $pid_file`); -kill 15, $pid; -sleep 0.25; - -# Verify that it's dead... -$output = `ps x | grep '^[ ]*$pid'`; -is( - $output, - '', - 'It is stopped now' -); - -$output = `ps -p $pid`; -unlike($output, qr/pt-query-digest/, 'It is stopped now'); - -$output = `grep read_only /tmp/read_only.txt`; -# Sample output: -# # main:3619 6897 read_only on execute for --execute: 1 (want 1) -# # main:3619 6897 read_only on processlist for --processlist: 0 (want 0) -# # main:3619 6897 read_only on processlist for --processlist: 0 (want 0) -# # main:3619 6897 read_only on processlist for --processlist: 0 (want 0) -# # main:3619 6897 read_only on processlist for --processlist: 0 (want 0) -# # main:3619 6897 read_only on processlist for --processlist: 0 (want 0) -# # main:3619 6897 read_only on processlist for --processlist: 0 (want 0) -# # main:3619 6897 read_only on execute for --execute: 0 (want 1) -# # main:3622 6897 read_only wrong for --execute getting a dbh from processlist -# # main:3619 6897 read_only on processlist for --processlist: 1 (want 0) -# # main:3622 6897 read_only wrong for --processlist getting a dbh from execute -# # main:3619 6897 read_only on processlist for --execute: 1 (want 1) -# # main:3619 6897 read_only on execute for --processlist: 0 (want 0) -like($output, qr/wrong for --execute getting a dbh from processlist/, - 'switching --processlist works'); -like($output, qr/wrong for --processlist getting a dbh from execute/, - 'switching --execute works'); - -diag(`rm -rf /tmp/read_only.txt`); - -# ############################################################################# -# Done. -# ############################################################################# -diag(`rm $pid_file 2>/dev/null`); -$dbh1->do('set global read_only=0'); -$dbh2->do('set global read_only=1'); -$sb->wipe_clean($dbh1); -ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); -exit; diff --git a/t/pt-query-digest/mysql_analyses.t b/t/pt-query-digest/mysql_analyses.t index 73632b76..e8bdd82d 100644 --- a/t/pt-query-digest/mysql_analyses.t +++ b/t/pt-query-digest/mysql_analyses.t @@ -9,7 +9,7 @@ BEGIN { use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); -use Test::More tests => 6; +use Test::More; use PerconaTest; @@ -76,7 +76,31 @@ ok( 'Analysis for tcpdump017 with microsecond timestamps (issue 398)' ); +# ############################################################################# +# Bug 1103045: pt-query-digest fails to parse non-SQL errors +# https://bugs.launchpad.net/percona-toolkit/+bug/1103045 +# ############################################################################# +ok( + no_diff( + sub { pt_query_digest::main(@args, $sample.'tcpdump043.txt', + '--report-format', 'header,query_report,profile', + qw(--watch-server 127.0.0.1:12345)) }, + "t/pt-query-digest/samples/tcpdump043_report.txt" + ), + 'Analysis for tcpdump043 with connection error (bug 1103045)' +); + +ok( + no_diff( + sub { pt_query_digest::main(@args, $sample.'tcpdump044.txt', + '--report-format', 'header,query_report,profile', + qw(--watch-server 100.0.0.1)) }, + "t/pt-query-digest/samples/tcpdump044_report.txt" + ), + 'Analysis for tcpdump044 with connection error (bug 1103045)' +); + # ############################################################################# # Done. # ############################################################################# -exit; +done_testing; diff --git a/t/pt-query-digest/option_sanity.t b/t/pt-query-digest/option_sanity.t index 5e4cf18a..1e177a62 100644 --- a/t/pt-query-digest/option_sanity.t +++ b/t/pt-query-digest/option_sanity.t @@ -13,14 +13,33 @@ use Test::More; use PerconaTest; +my $cmd = "$trunk/bin/pt-query-digest"; +my $help = qx{$cmd --help}; + +my $output; + # ############################################################################# # Test cmd line op sanity. # ############################################################################# -my $output = `$trunk/bin/pt-query-digest --review h=127.1,P=12345,u=msandbox,p=msandbox`; -like($output, qr/--review DSN requires a D/, 'Dies if no D part in --review DSN'); +for my $opt (qw(review-table history-table)) { + $output = `$cmd --review h=127.1,P=12345,u=msandbox,p=msandbox --$opt test`; + like($output, qr/--$opt should be passed a/, "Dies if no database part in --$opt"); +} -$output = `$trunk/bin/pt-query-digest --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test`; -like($output, qr/--review DSN requires a D/, 'Dies if no t part in --review DSN'); +$output = `$cmd --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=test`; +like($output, qr/--review does not accept a t option/, 'Dies if t part in --review DSN'); + +like( + $help, + qr/review-table\s+\Qpercona_schema.query_review\E/, + "--review-table has a sane default" +); + +like( + $help, + qr/history-table\s+\Qpercona_schema.query_history\E/, + "--history-table has a sane default" +); # ############################################################################# # https://bugs.launchpad.net/percona-toolkit/+bug/885382 @@ -34,43 +53,59 @@ my @options = qw( --group-by file ); -$output = `$trunk/bin/pt-query-digest @options --embedded-attributes '-- .*' $sample.slow010.txt`; +$output = `$cmd @options --embedded-attributes '-- .*' $sample.slow010.txt`; like $output, qr/\Q--embedded-attributes should be passed two comma-separated patterns, got 1/, 'Bug 885382: --embedded-attributes cardinality'; -$output = `$trunk/bin/pt-query-digest @options --embedded-attributes '-- .*,(?{1234})' $sample.slow010.txt`; +$output = `$cmd @options --embedded-attributes '-- .*,(?{1234})' $sample.slow010.txt`; like $output, qr/\Q--embedded-attributes Eval-group /, "Bug 885382: --embedded-attributes rejects invalid patterns early"; -$output = `$trunk/bin/pt-query-digest @options --embedded-attributes '-- .*,(?*asdasd' $sample.slow010.txt`; +$output = `$cmd @options --embedded-attributes '-- .*,(?*asdasd' $sample.slow010.txt`; like $output, qr/\Q--embedded-attributes Sequence (?*...) not recognized/, "Bug 885382: --embedded-attributes rejects invalid patterns early"; -$output = `$trunk/bin/pt-query-digest @options --embedded-attributes '-- .*,[:alpha:]' $sample.slow010.txt`; +$output = `$cmd @options --embedded-attributes '-- .*,[:alpha:]' $sample.slow010.txt`; like $output, qr/\Q--embedded-attributes POSIX syntax [: :] belongs inside character/, "Bug 885382: --embedded-attributes rejects warning patterns early";; + +# We removed --statistics, but they should still print out if we use PTDEBUG. + +$output = qx{PTDEBUG=1 $cmd --no-report ${sample}slow002.txt 2>&1}; +my $stats = slurp_file("t/pt-query-digest/samples/stats-slow002.txt"); + +like( + $output, + qr/\Q$stats\E/m, + 'PTDEBUG shows --statistics for slow002.txt', +); + +like( + $output, + qr/Pipeline profile/m, + 'PTDEBUG shows --pipeline-profile' +); + # ############################################################################# # pt-query-digest help output mangled # https://bugs.launchpad.net/percona-toolkit/+bug/831525 # ############################################################################# -$output = `$trunk/bin/pt-query-digest --help`; - like( - $output, + $help, qr/\Q--report-format=A\E\s* \QPrint these sections of the query analysis\E\s* - \Qreport (default rusage,date,hostname,files,\E\s* - \Qheader,profile,query_report,prepared)\E/x, + \Qreport (default rusage\E,\s*date,\s*hostname,\s*files,\s* + header,\s*profile,\s*query_report,\s*prepared\)/x, "Bug 831525: pt-query-digest help output mangled" ); diff --git a/t/pt-query-digest/output.t b/t/pt-query-digest/output.t new file mode 100644 index 00000000..f61bb572 --- /dev/null +++ b/t/pt-query-digest/output.t @@ -0,0 +1,55 @@ +#!/usr/bin/env perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +use PerconaTest; +require "$trunk/bin/pt-query-digest"; + +no warnings 'once'; +local $JSONReportFormatter::sorted_json = 1; +local $JSONReportFormatter::pretty_json = 1; + +my @args = qw(--output json); +my $sample = "$trunk/t/lib/samples"; +my $results = "t/pt-query-digest/samples"; + +ok( + no_diff( + sub { pt_query_digest::main(@args, "$sample/slowlogs/empty") }, + "$results/empty_report.txt", + ), + 'json output for empty log' +); + +ok( + no_diff( + sub { pt_query_digest::main(@args, "$sample/slowlogs/slow002.txt") }, + "$results/output_json_slow002.txt" + ), + 'json output for slow002' +); + +# --type tcpdump + +ok( + no_diff( + sub { pt_query_digest::main(qw(--type tcpdump --limit 10 --watch-server 127.0.0.1:12345), + @args, "$sample/tcpdump/tcpdump021.txt") }, + "$results/output_json_tcpdump021.txt", + ), + 'json output for for tcpdump021', +); + +# ############################################################################# +# Done. +# ############################################################################# +done_testing; diff --git a/t/pt-query-digest/resume.t b/t/pt-query-digest/resume.t new file mode 100644 index 00000000..ccc2ca65 --- /dev/null +++ b/t/pt-query-digest/resume.t @@ -0,0 +1,163 @@ +#!/usr/bin/env perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +use IO::File; +use Fcntl qw(:seek); +use File::Temp qw(tempfile); + +use PerconaTest; +use Sandbox; +require "$trunk/bin/pt-query-digest"; + +my $dp = new DSNParser(opts=>$dsn_opts); +my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); +my $dbh = $sb->get_dbh_for('master'); + +if ( !$dbh ) { + plan skip_all => 'Cannot connect to sandbox master'; +} + +my $samples = "$trunk/t/lib/samples/slowlogs"; +my $output; + +$sb->create_dbs($dbh, ['test']); + +my $resume_file = (tempfile())[1]; + +my ($fh, $filename) = tempfile(UNLINK => 1); +$fh->autoflush(1); + +sub resume_offset_ok { + my ($resume_file, $file, $msg) = @_; + chomp(my $offset = slurp_file($resume_file)); + open my $tmp_fh, q{<}, $file or die $OS_ERROR; + seek $tmp_fh, 0, SEEK_END; + is(tell($tmp_fh), $offset, $msg); +} + +sub run_pqd { + my @extra_args = @_; + my $run = output(sub { pt_query_digest::main(qw(--limit 10), @extra_args, $filename) }, stderr => 1); + $run =~ s/\d+ms user time.+//; + $run =~ s/Current date: .+//; + return $run; +} + +print { $fh } slurp_file("$samples/slow006.txt"); + +my @runs; +push @runs, run_pqd() for 1, 2; + +is($runs[0], $runs[1], "Sanity check: Behaves the same between runs without --resume"); + +my @resume_runs; +push @resume_runs, run_pqd('--resume', $resume_file) for 1, 2; + +(my $without_resume_line = $resume_runs[0]) =~ s/\n\n. Saved resume file offset.+//; +is( + $runs[0], + $without_resume_line, + "First time with --resume just like the first time without" +); + +like( + $resume_runs[0], + qr/\QSaved resume file offset\E/, + "SAves offset with --resume" +); + +like( + $resume_runs[1], + qr/\QNo events processed.\E/, + "..and there are no events on the second run" +); + +resume_offset_ok($resume_file, $filename, "The resume file has the correct offset"); + +print { $fh } slurp_file("$samples/slow002.txt"); + +push @resume_runs, run_pqd('--resume', $resume_file) for 1, 2; + +unlike( + $resume_runs[2], + qr/\QNo events processed.\E/, + "New run detects new events" +); + +like( + $resume_runs[3], + qr/\QNo events processed.\E/, + "And running again after that finds nothing new" +); + +resume_offset_ok($resume_file, $filename, "The resume file has the updated offset"); + +unlink($resume_file); + +close $fh; + +# ############################################################################# +# Now test the itneraction with --run-time-mode interval +# ############################################################################# + +($fh, $filename) = tempfile(UNLINK => 1); +$fh->autoflush(1); + +print { $fh } slurp_file("$trunk/t/lib/samples/slowlogs/slow033.txt"); + +my @run_args = (qw(--run-time-mode interval --run-time 1d --iterations 0), + qw(--report-format query_report)); +my @resume_args = (@run_args, '--resume', $resume_file); + +my @run_time; +push @run_time, run_pqd(@resume_args) for 1,2; + +resume_offset_ok($resume_file, $filename, "The resume file has the correct offset when using --run-time-mode interval"); + +print { $fh } slurp_file("$samples/slow002.txt"); + +push @run_time, run_pqd(@resume_args) for 1,2; + +resume_offset_ok($resume_file, $filename, "...and it updates correctly"); + +like( + $_, + qr/\QNo events processed.\E/, + "Runs 2 & 4 find no new data" +) for @run_time[1, 3]; + +# This shows up in the first report, but shouldn't show up in there +# third run, after we add new events to the file. +my $re = qr/\QSELECT * FROM foo\E/; + +unlike( + $run_time[2], + $re, + "Events from the first run are correctly ignored" +); + +my $no_resume = run_pqd(@run_args); + +like( + $no_resume, + $re, + "...but do show up if run without resume" +); + +# ############################################################################# +# Done. +# ############################################################################# +$sb->wipe_clean($dbh); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +done_testing; +exit; diff --git a/t/pt-query-digest/review.t b/t/pt-query-digest/review.t index bf980c3d..8ad93f76 100644 --- a/t/pt-query-digest/review.t +++ b/t/pt-query-digest/review.t @@ -22,9 +22,6 @@ my $dbh = $sb->get_dbh_for('master'); if ( !$dbh ) { plan skip_all => 'Cannot connect to sandbox master'; } -else { - plan tests => 18; -} sub normalize_numbers { use Scalar::Util qw(looks_like_number); @@ -43,21 +40,21 @@ $sb->load_file('master', 't/pt-query-digest/samples/query_review.sql'); # Test --create-review and --create-review-history-table $output = 'foo'; # clear previous test results -$cmd = "${run_with}slow006.txt --create-review-table --review " - . "h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=query_review --create-review-history-table " - . "--review-history t=query_review_history"; +$cmd = "${run_with}slow006.txt --create-review-tables --review " + . "h=127.1,P=12345,u=msandbox,p=msandbox --review-table test.query_review " + . "--history-table test.query_review_history"; $output = `$cmd >/dev/null 2>&1`; my ($table) = $dbh->selectrow_array( "show tables from test like 'query_review'"); -is($table, 'query_review', '--create-review'); +is($table, 'query_review', '--create-review-tables'); ($table) = $dbh->selectrow_array( "show tables from test like 'query_review_history'"); -is($table, 'query_review_history', '--create-review-history-table'); +is($table, 'query_review_history', '--create-review-tables'); $output = 'foo'; # clear previous test results -$cmd = "${run_with}slow006.txt --review h=127.1,u=msandbox,p=msandbox,P=12345,D=test,t=query_review " - . "--review-history t=query_review_history"; +$cmd = "${run_with}slow006.txt --review h=127.1,u=msandbox,p=msandbox,P=12345 --review-table test.query_review " + . "--history-table test.query_review_history"; $output = `$cmd`; my $res = $dbh->selectall_arrayref( 'SELECT * FROM test.query_review', { Slice => {} } ); @@ -181,17 +178,21 @@ is_deeply( # have been reviewed, the report should include both of them with # their respective query review info added to the report. ok( - no_diff($run_with.'slow006.txt --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=query_review', "t/pt-query-digest/samples/slow006_AR_1.txt"), + no_diff($run_with.'slow006.txt --review h=127.1,P=12345,u=msandbox,p=msandbox --review-table test.query_review --create-review-tables', "t/pt-query-digest/samples/slow006_AR_1.txt"), 'Analyze-review pass 1 reports not-reviewed queries' ); +($table) = $dbh->selectrow_array( + "show tables from percona_schema like 'query_history'"); +is($table, 'query_history', '--create-review-tables creates both percona_schema and query_review_history'); + # Mark a query as reviewed and run --report again and that query should # not be reported. $dbh->do('UPDATE test.query_review SET reviewed_by="daniel", reviewed_on="2008-12-24 12:00:00", comments="foo_tbl is ok, so are cranberries" WHERE checksum=11676753765851784517'); ok( - no_diff($run_with.'slow006.txt --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=query_review', "t/pt-query-digest/samples/slow006_AR_2.txt"), + no_diff($run_with.'slow006.txt --review h=127.1,P=12345,u=msandbox,p=msandbox --review-table test.query_review', "t/pt-query-digest/samples/slow006_AR_2.txt"), 'Analyze-review pass 2 does not report the reviewed query' ); @@ -199,7 +200,7 @@ ok( # to re-appear in the report with the reviewed_by, reviewed_on and comments # info included. ok( - no_diff($run_with.'slow006.txt --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=query_review --report-all', "t/pt-query-digest/samples/slow006_AR_4.txt"), + no_diff($run_with.'slow006.txt --review h=127.1,P=12345,u=msandbox,p=msandbox --review-table test.query_review --report-all', "t/pt-query-digest/samples/slow006_AR_4.txt"), 'Analyze-review pass 4 with --report-all reports reviewed query' ); @@ -208,7 +209,7 @@ $dbh->do('ALTER TABLE test.query_review ADD COLUMN foo INT'); $dbh->do('UPDATE test.query_review SET foo=42 WHERE checksum=15334040482108055940'); ok( - no_diff($run_with.'slow006.txt --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=query_review', "t/pt-query-digest/samples/slow006_AR_5.txt"), + no_diff($run_with.'slow006.txt --review h=127.1,P=12345,u=msandbox,p=msandbox --review-table test.query_review', "t/pt-query-digest/samples/slow006_AR_5.txt"), 'Analyze-review pass 5 reports new review info column' ); @@ -217,7 +218,7 @@ ok( $dbh->do("update test.query_review set first_seen='0000-00-00 00:00:00', " . " last_seen='0000-00-00 00:00:00'"); $output = 'foo'; # clear previous test results -$cmd = "${run_with}slow022.txt --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=query_review"; +$cmd = "${run_with}slow022.txt --review h=127.1,P=12345,u=msandbox,p=msandbox --review-table test.query_review"; $output = `$cmd`; unlike($output, qr/last_seen/, 'no last_seen when 0000 timestamp'); unlike($output, qr/first_seen/, 'no first_seen when 0000 timestamp'); @@ -231,7 +232,7 @@ unlike($output, qr/0000-00-00 00:00:00/, 'no 0000-00-00 00:00:00 timestamp'); # Make sure a missing Time property does not cause a crash. Don't test data # in table, because it varies based on when you run the test. $output = 'foo'; # clear previous test results -$cmd = "${run_with}slow021.txt --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=query_review"; +$cmd = "${run_with}slow021.txt --review h=127.1,P=12345,u=msandbox,p=msandbox --review-table test.query_review"; $output = `$cmd`; unlike($output, qr/Use of uninitialized value/, 'didnt crash due to undef ts'); @@ -239,7 +240,7 @@ unlike($output, qr/Use of uninitialized value/, 'didnt crash due to undef ts'); # crash. Don't test data in table, because it varies based on when you run # the test. $output = 'foo'; # clear previous test results -$cmd = "${run_with}slow022.txt --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=query_review"; +$cmd = "${run_with}slow022.txt --review h=127.1,P=12345,u=msandbox,p=msandbox --review-table test.query_review"; $output = `$cmd`; # Don't test data in table, because it varies based on when you run the test. unlike($output, qr/Use of uninitialized value/, 'no crash due to totally missing ts'); @@ -248,7 +249,7 @@ unlike($output, qr/Use of uninitialized value/, 'no crash due to totally missing # --review --no-report # ############################################################################# $sb->load_file('master', 't/pt-query-digest/samples/query_review.sql'); -$output = `${run_with}slow006.txt --review h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=query_review --no-report --create-review-table`; +$output = `${run_with}slow006.txt --review h=127.1,P=12345,u=msandbox,p=msandbox --review-table test.query_review --no-report --create-review-table`; $res = $dbh->selectall_arrayref('SELECT * FROM test.query_review'); is( $res->[0]->[1], @@ -268,7 +269,7 @@ is( $dbh->do('truncate table test.query_review'); $dbh->do('truncate table test.query_review_history'); -`${run_with}slow002.txt --review h=127.1,u=msandbox,p=msandbox,P=12345,D=test,t=query_review --review-history t=query_review_history --no-report --filter '\$event->{arg} =~ m/foo\.bar/' > /dev/null`; +`${run_with}slow002.txt --review h=127.1,u=msandbox,p=msandbox,P=12345 --review-table test.query_review --history-table test.query_review_history --no-report --filter '\$event->{arg} =~ m/foo\.bar/' > /dev/null`; $res = $dbh->selectall_arrayref( 'SELECT * FROM test.query_review_history', { Slice => {} } ); @@ -396,8 +397,9 @@ $dbh->do($min_tbl); $output = output( sub { pt_query_digest::main( - '--review', 'h=127.1,u=msandbox,p=msandbox,P=12345,D=test,t=query_review', - '--review-history', 't=query_review_history', + '--review', 'h=127.1,u=msandbox,p=msandbox,P=12345', + '--review-table', 'test.query_review', + '--history-table', 'test.query_review_history', qw(--no-report --no-continue-on-error), "$trunk/t/lib/samples/slow002.txt") }, @@ -415,4 +417,5 @@ unlike( # ############################################################################# $sb->wipe_clean($dbh); ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +done_testing; exit; diff --git a/t/pt-query-digest/samples/binlog001.txt b/t/pt-query-digest/samples/binlog001.txt index b6acca7b..d4ac8514 100644 --- a/t/pt-query-digest/samples/binlog001.txt +++ b/t/pt-query-digest/samples/binlog001.txt @@ -15,8 +15,7 @@ # error code 0 0 0 0 0 0 0 # Query 1: 0 QPS, 0x concurrency, ID 0xCD948EAF18BC614E at byte 953 ______ -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-07 12:02:08 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -52,8 +51,7 @@ replace into test4.tbl9(tbl5, day, todo, comment) and o.col3 >= date_sub(current_date, interval 30 day)\G # Query 2: 0 QPS, 0x concurrency, ID 0xC356FD9EFD7D799E at byte 605 ______ -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-07 12:02:07 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -89,8 +87,7 @@ select e.tblo = o.tblo, inner join test3.tbl2 as e on o.animal = e.animal and o.oid = e.oid where e.tblo is null\G # Query 3: 0 QPS, 0x concurrency, ID 0xB5E55291C7DE1096 at byte 1469 _____ -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-07 12:02:50 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -126,8 +123,7 @@ select o.tbl2 = e.tbl2, on o.animal = e.animal and o.oid = e.oid where o.tbl2 is null\G # Query 4: 0 QPS, 0x concurrency, ID 0x85FFF5AA78E5FF6A at byte 146 ______ -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-07 12:02:50 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -156,8 +152,7 @@ select o.tbl2 = e.tbl2, BEGIN\G # Query 5: 0 QPS, 0x concurrency, ID 0xED69B13F3D0161D0 at byte 2479 _____ -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-07 12:02:53 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -191,8 +186,7 @@ select last2metric1 = last1metric1, last2time = last1time, last0metric1 = ondeckmetric1, last0time = now() from test2.tbl8 where tbl8 in (10800712)\G # Query 6: 0 QPS, 0x concurrency, ID 0x79BFEA84D0CED05F at byte 1889 _____ -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-07 12:02:53 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -222,11 +216,11 @@ insert into test1.tbl6 metric12 = metric12 + values(metric12), secs = secs + values(secs)\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Ite -# ==== ================== ================ ===== ========== ==== ===== === -# 1 0xCD948EAF18BC614E 20704.0000 16.7% 1 20704.0000 0.00 0.00 REPLACE SELECT test?.tbl? test?.tblo test?.tbl? -# 2 0xC356FD9EFD7D799E 20675.0000 16.7% 1 20675.0000 0.00 0.00 UPDATE test?.tblo test?.tbl? -# 3 0xB5E55291C7DE1096 20664.0000 16.7% 1 20664.0000 0.00 0.00 UPDATE test?.tblo test?.tbl? -# 4 0x85FFF5AA78E5FF6A 20664.0000 16.7% 1 20664.0000 0.00 0.00 BEGIN -# 5 0xED69B13F3D0161D0 20661.0000 16.7% 1 20661.0000 0.00 0.00 UPDATE test?.tbl? -# 6 0x79BFEA84D0CED05F 20661.0000 16.7% 1 20661.0000 0.00 0.00 INSERT UPDATE test?.tbl? +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ================ ===== ========== ===== ======== +# 1 0xCD948EAF18BC614E 20704.0000 16.7% 1 20704.0000 0.00 REPLACE SELECT test?.tbl? test?.tblo test?.tbl? +# 2 0xC356FD9EFD7D799E 20675.0000 16.7% 1 20675.0000 0.00 UPDATE test?.tblo test?.tbl? +# 3 0xB5E55291C7DE1096 20664.0000 16.7% 1 20664.0000 0.00 UPDATE test?.tblo test?.tbl? +# 4 0x85FFF5AA78E5FF6A 20664.0000 16.7% 1 20664.0000 0.00 BEGIN +# 5 0xED69B13F3D0161D0 20661.0000 16.7% 1 20661.0000 0.00 UPDATE test?.tbl? +# 6 0x79BFEA84D0CED05F 20661.0000 16.7% 1 20661.0000 0.00 INSERT UPDATE test?.tbl? diff --git a/t/pt-query-digest/samples/binlog002.txt b/t/pt-query-digest/samples/binlog002.txt index 076171f9..3e1426a2 100644 --- a/t/pt-query-digest/samples/binlog002.txt +++ b/t/pt-query-digest/samples/binlog002.txt @@ -16,8 +16,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xF25D6D5AC7C18FF3 at byte 381 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-22 07:21:59 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -45,8 +44,7 @@ create database d\G # Query 2: 0 QPS, 0x concurrency, ID 0x03409022EB8A4AE7 at byte 795 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-22 07:22:16 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -72,8 +70,7 @@ create table foo (i int)\G # Query 3: 0 QPS, 0x concurrency, ID 0xF579EC4A9633EEA0 at byte 973 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-22 07:22:24 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -95,8 +92,8 @@ create table foo (i int)\G insert foo values (1) /*... omitted ...*/\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xF25D6D5AC7C18FF3 0.0000 0.0% 1 0.0000 1.00 0.00 CREATE DATABASE d -# 2 0x03409022EB8A4AE7 0.0000 0.0% 1 0.0000 1.00 0.00 CREATE TABLE foo -# 3 0xF579EC4A9633EEA0 0.0000 0.0% 1 0.0000 1.00 0.00 INSERT +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== =============== +# 1 0xF25D6D5AC7C18FF3 0.0000 0.0% 1 0.0000 0.00 CREATE DATABASE d +# 2 0x03409022EB8A4AE7 0.0000 0.0% 1 0.0000 0.00 CREATE TABLE foo +# 3 0xF579EC4A9633EEA0 0.0000 0.0% 1 0.0000 0.00 INSERT diff --git a/t/pt-query-digest/samples/cannot-distill-profile.txt b/t/pt-query-digest/samples/cannot-distill-profile.txt index de462a62..60a42713 100644 --- a/t/pt-query-digest/samples/cannot-distill-profile.txt +++ b/t/pt-query-digest/samples/cannot-distill-profile.txt @@ -1,6 +1,6 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x5B721CAE3EDDB56B 0.0900 69.1% 1 0.0900 1.00 0.00 -# 2 0xBE90A42C0FB7E89E 0.0403 30.9% 1 0.0403 1.00 0.00 +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== =========== +# 1 0x5B721CAE3EDDB56B 0.0900 69.1% 1 0.0900 0.00 +# 2 0xBE90A42C0FB7E89E 0.0403 30.9% 1 0.0403 0.00 diff --git a/t/pt-query-digest/samples/genlog001.txt b/t/pt-query-digest/samples/genlog001.txt index a08e68e9..63b9ce91 100644 --- a/t/pt-query-digest/samples/genlog001.txt +++ b/t/pt-query-digest/samples/genlog001.txt @@ -7,8 +7,7 @@ # Query size 315 27 124 45 118.34 31.33 28.75 # Query 1: 0.00 QPS, 0x concurrency, ID 0x5D51E5F01B88B79E at byte 244 ___ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: 2005-10-07 21:55:24 to 2006-12-26 15:42:36 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -31,8 +30,7 @@ administrator command: Connect\G # Query 2: 0.00 QPS, 0x concurrency, ID 0xAA353644DE4C4CB4 at byte 464 ___ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: 2005-10-07 21:55:24 to 2006-12-26 16:44:48 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -53,8 +51,7 @@ administrator command: Connect\G administrator command: Quit\G # Query 3: 0 QPS, 0x concurrency, ID 0x4D096479916B0F45 at byte 346 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2006-12-26 15:42:36 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -79,8 +76,7 @@ administrator command: Quit\G SELECT DISTINCT col FROM tbl WHERE foo=20061219\G # Query 4: 0 QPS, 0x concurrency, ID 0x44AAC79F41BCF692 at byte 58 _______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2005-10-07 21:55:24 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -108,8 +104,7 @@ SELECT foo ORDER BY col\G # Query 5: 0 QPS, 0x concurrency, ID 0x44AE35A182869033 at byte 300 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2006-12-26 15:42:36 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -130,10 +125,10 @@ SELECT foo administrator command: Init DB\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x5D51E5F01B88B79E 0.0000 0.0% 2 0.0000 1.00 0.00 ADMIN CONNECT -# 2 0xAA353644DE4C4CB4 0.0000 0.0% 2 0.0000 1.00 0.00 ADMIN QUIT -# 3 0x4D096479916B0F45 0.0000 0.0% 1 0.0000 1.00 0.00 SELECT tbl -# 4 0x44AAC79F41BCF692 0.0000 0.0% 1 0.0000 1.00 0.00 SELECT tbl -# 5 0x44AE35A182869033 0.0000 0.0% 1 0.0000 1.00 0.00 ADMIN INIT DB +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ============= +# 1 0x5D51E5F01B88B79E 0.0000 0.0% 2 0.0000 0.00 ADMIN CONNECT +# 2 0xAA353644DE4C4CB4 0.0000 0.0% 2 0.0000 0.00 ADMIN QUIT +# 3 0x4D096479916B0F45 0.0000 0.0% 1 0.0000 0.00 SELECT tbl +# 4 0x44AAC79F41BCF692 0.0000 0.0% 1 0.0000 0.00 SELECT tbl +# 5 0x44AE35A182869033 0.0000 0.0% 1 0.0000 0.00 ADMIN INIT DB diff --git a/t/pt-query-digest/samples/genlog002.txt b/t/pt-query-digest/samples/genlog002.txt index 5afe0258..fb0937bc 100644 --- a/t/pt-query-digest/samples/genlog002.txt +++ b/t/pt-query-digest/samples/genlog002.txt @@ -8,8 +8,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x2361B36A4AEB397B at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2010-02-11 00:55:24 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -35,8 +34,7 @@ SELECT category_id # Query 2: 0 QPS, 0x concurrency, ID 0x0A3E6DCD23F3445A at byte 237 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2010-02-11 00:55:24 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -71,7 +69,7 @@ SELECT auction_id, auction_title_en AS title, close_time, LIMIT 500\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x2361B36A4AEB397B 0.0000 0.0% 1 0.0000 1.00 0.00 SELECT auction_category_map -# 2 0x0A3E6DCD23F3445A 0.0000 0.0% 1 0.0000 1.00 0.00 SELECT auction_search +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== =============== +# 1 0x2361B36A4AEB397B 0.0000 0.0% 1 0.0000 0.00 SELECT auction_category_map +# 2 0x0A3E6DCD23F3445A 0.0000 0.0% 1 0.0000 0.00 SELECT auction_search diff --git a/t/pt-query-digest/samples/genlog003.txt b/t/pt-query-digest/samples/genlog003.txt index 5330867f..98de2ae3 100644 --- a/t/pt-query-digest/samples/genlog003.txt +++ b/t/pt-query-digest/samples/genlog003.txt @@ -7,8 +7,7 @@ # Query size 315 27 124 45 118.34 31.33 28.75 # Query 1: 0 QPS, 0x concurrency, ID 0x5D51E5F01B88B79E at byte 246 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2005-10-07 21:55:24 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -31,8 +30,7 @@ administrator command: Connect\G # Query 2: 0 QPS, 0x concurrency, ID 0xAA353644DE4C4CB4 at byte 466 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2005-10-07 21:55:24 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -53,8 +51,7 @@ administrator command: Connect\G administrator command: Quit\G # Query 3: 0 QPS, 0x concurrency, ID 0x4D096479916B0F45 at byte 348 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2005-10-07 21:55:24 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -79,8 +76,7 @@ administrator command: Quit\G SELECT DISTINCT col FROM tbl WHERE foo=20061219\G # Query 4: 0 QPS, 0x concurrency, ID 0x44AAC79F41BCF692 at byte 60 _______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2005-10-07 21:55:24 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -108,8 +104,7 @@ SELECT foo ORDER BY col\G # Query 5: 0 QPS, 0x concurrency, ID 0x44AE35A182869033 at byte 302 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2005-10-07 21:55:24 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -130,10 +125,10 @@ SELECT foo administrator command: Init DB\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x5D51E5F01B88B79E 0.0000 0.0% 2 0.0000 1.00 0.00 ADMIN CONNECT -# 2 0xAA353644DE4C4CB4 0.0000 0.0% 2 0.0000 1.00 0.00 ADMIN QUIT -# 3 0x4D096479916B0F45 0.0000 0.0% 1 0.0000 1.00 0.00 SELECT tbl -# 4 0x44AAC79F41BCF692 0.0000 0.0% 1 0.0000 1.00 0.00 SELECT tbl -# 5 0x44AE35A182869033 0.0000 0.0% 1 0.0000 1.00 0.00 ADMIN INIT DB +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ============= +# 1 0x5D51E5F01B88B79E 0.0000 0.0% 2 0.0000 0.00 ADMIN CONNECT +# 2 0xAA353644DE4C4CB4 0.0000 0.0% 2 0.0000 0.00 ADMIN QUIT +# 3 0x4D096479916B0F45 0.0000 0.0% 1 0.0000 0.00 SELECT tbl +# 4 0x44AAC79F41BCF692 0.0000 0.0% 1 0.0000 0.00 SELECT tbl +# 5 0x44AE35A182869033 0.0000 0.0% 1 0.0000 0.00 ADMIN INIT DB diff --git a/t/pt-query-digest/samples/http_tcpdump002.txt b/t/pt-query-digest/samples/http_tcpdump002.txt index 4d48f8a7..8fdd14fc 100644 --- a/t/pt-query-digest/samples/http_tcpdump002.txt +++ b/t/pt-query-digest/samples/http_tcpdump002.txt @@ -1,7 +1,6 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xFB0C089DD4451762 at byte 59213 ____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-11-09 15:31:09.411349 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -25,8 +24,7 @@ get www.percona.com/images/menu_our-vision.gif # Query 2: 0 QPS, 0x concurrency, ID 0x7C3AA9143C98C14A at byte 206 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-11-09 15:31:09.074855 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -50,8 +48,7 @@ get www.percona.com/images/menu_our-vision.gif get www.percona.com/about-us.html # Query 3: 0 QPS, 0x concurrency, ID 0x7CC09CE55CB7750C at byte 16362 ____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-11-09 15:31:09.157215 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -75,8 +72,7 @@ get www.percona.com/about-us.html get www.percona.com/js/jquery.js # Query 4: 0 QPS, 0x concurrency, ID 0x44C0C94594575296 at byte 65644 ____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-11-09 15:31:09.420851 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -100,8 +96,7 @@ get www.percona.com/js/jquery.js get www.percona.com/images/bg-gray-corner-top.gif # Query 5: 0 QPS, 0x concurrency, ID 0x08207FBDE8A42C36 at byte 67956 ____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-11-09 15:31:09.420996 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -125,8 +120,7 @@ get www.percona.com/images/bg-gray-corner-top.gif get www.percona.com/images/handshake.jpg # Query 6: 0 QPS, 0x concurrency, ID 0x4F1E2B5E822F55B8 at byte 53100 ____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-11-09 15:31:09.346763 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -150,8 +144,7 @@ get www.percona.com/images/handshake.jpg get www.percona.com/images/menu_team.gif # Query 7: 0 QPS, 0x concurrency, ID 0x7FB624EE10D71E1F at byte 170117 ___ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-11-09 15:31:14.737890 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -175,8 +168,7 @@ get www.percona.com/images/menu_team.gif get hit.clickaider.com/s/forms.js # Query 8: 0 QPS, 0x concurrency, ID 0x1279DE4968C95A8D at byte 147447 ___ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-11-09 15:31:14.536149 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -200,8 +192,7 @@ get hit.clickaider.com/s/forms.js get hit.clickaider.com/clickaider.js # Query 9: 0 QPS, 0x concurrency, ID 0x590BE2A84B8F0D5B at byte 167245 ___ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-11-09 15:31:14.678713 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -225,8 +216,7 @@ get hit.clickaider.com/clickaider.js get hit.clickaider.com/pv?lng=140&&lnks=&t=About%20Percona&c=73a41b95-2926&r=http%3A%2F%2Fwww.percona.com%2F&tz=-420&loc=http%3A%2F%2Fwww.percona.com%2Fabout-us.html&rnd=3688 # Query 10: 0 QPS, 0x concurrency, ID 0xFC5C4A690D695F35 at byte 55942 ___ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-11-09 15:31:09.373800 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/issue_1196-output-5.0.txt b/t/pt-query-digest/samples/issue_1196-output-5.0.txt index 17eaefa0..8d0edc99 100644 --- a/t/pt-query-digest/samples/issue_1196-output-5.0.txt +++ b/t/pt-query-digest/samples/issue_1196-output-5.0.txt @@ -1,14 +1,12 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M EXPLAIN Item -# ==== ================== ============= ===== ====== ==== ===== ======= ======== -# 1 0xD4B6A5CD2F2F485C 0.2148 100.0% 1 0.2148 1.00 0.00 TF>aa SELECT t +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ======== +# 1 0xD4B6A5CD2F2F485C 0.2148 100.0% 1 0.2148 0.00 SELECT t # Query 1: 0 QPS, 0x concurrency, ID 0xD4B6A5CD2F2F485C at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# EXPLAIN sparkline: TF>aa -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2010-12-14 16:12:28 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/issue_1196-output-5.6.txt b/t/pt-query-digest/samples/issue_1196-output-5.6.txt index bd69285f..860ec6b5 100644 --- a/t/pt-query-digest/samples/issue_1196-output-5.6.txt +++ b/t/pt-query-digest/samples/issue_1196-output-5.6.txt @@ -1,14 +1,12 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M EXPLAIN Item -# ==== ================== ============= ===== ====== ==== ===== ======= ======== -# 1 0xD4B6A5CD2F2F485C 0.2148 100.0% 1 0.2148 1.00 0.00 TF>aa SELECT t +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ======== +# 1 0xD4B6A5CD2F2F485C 0.2148 100.0% 1 0.2148 0.00 SELECT t # Query 1: 0 QPS, 0x concurrency, ID 0xD4B6A5CD2F2F485C at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# EXPLAIN sparkline: TF>aa -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2010-12-14 16:12:28 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/issue_1196-output.txt b/t/pt-query-digest/samples/issue_1196-output.txt index d7b2e2ef..71d380f8 100644 --- a/t/pt-query-digest/samples/issue_1196-output.txt +++ b/t/pt-query-digest/samples/issue_1196-output.txt @@ -1,14 +1,12 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M EXPLAIN Item -# ==== ================== ============= ===== ====== ==== ===== ======= ======== -# 1 0xD4B6A5CD2F2F485C 0.2148 100.0% 1 0.2148 1.00 0.00 TF>aa SELECT t +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ======== +# 1 0xD4B6A5CD2F2F485C 0.2148 100.0% 1 0.2148 0.00 SELECT t # Query 1: 0 QPS, 0x concurrency, ID 0xD4B6A5CD2F2F485C at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# EXPLAIN sparkline: TF>aa -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2010-12-14 16:12:28 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump001.txt b/t/pt-query-digest/samples/memc_tcpdump001.txt index d8966641..e300ad76 100644 --- a/t/pt-query-digest/samples/memc_tcpdump001.txt +++ b/t/pt-query-digest/samples/memc_tcpdump001.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x26193ADA9E14A97E at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-04 21:33:39.229179 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump002.txt b/t/pt-query-digest/samples/memc_tcpdump002.txt index c94b74b9..3b0720c4 100644 --- a/t/pt-query-digest/samples/memc_tcpdump002.txt +++ b/t/pt-query-digest/samples/memc_tcpdump002.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x456F2F160AF2DC0F at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-04 22:12:06.174390 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump003.txt b/t/pt-query-digest/samples/memc_tcpdump003.txt index 5b950344..b0bb5ff4 100644 --- a/t/pt-query-digest/samples/memc_tcpdump003.txt +++ b/t/pt-query-digest/samples/memc_tcpdump003.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAEBF67014CC9A7C0 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-04 22:12:06.175734 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -27,8 +26,7 @@ incr key # Query 2: 0 QPS, 0x concurrency, ID 0xC03129972E1D6A1F at byte 522 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-04 22:12:06.176181 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump003_report_key_print.txt b/t/pt-query-digest/samples/memc_tcpdump003_report_key_print.txt index a04d0331..df88fe79 100644 --- a/t/pt-query-digest/samples/memc_tcpdump003_report_key_print.txt +++ b/t/pt-query-digest/samples/memc_tcpdump003_report_key_print.txt @@ -5,8 +5,7 @@ # Item 1: 4.47k QPS, 0.32x concurrency, ID 0x8228B9A98CA1531D at byte 0 __ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-07-04 22:12:06.175734 to 22:12:06.176181 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump004.txt b/t/pt-query-digest/samples/memc_tcpdump004.txt index 27acc028..b7d8f2aa 100644 --- a/t/pt-query-digest/samples/memc_tcpdump004.txt +++ b/t/pt-query-digest/samples/memc_tcpdump004.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAEBF67014CC9A7C0 at byte 764 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-06 10:37:21.668469 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -28,8 +27,7 @@ incr key # Query 2: 0 QPS, 0x concurrency, ID 0xC03129972E1D6A1F at byte 1788 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-06 10:37:21.668851 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump005.txt b/t/pt-query-digest/samples/memc_tcpdump005.txt index da7a20c0..838774b6 100644 --- a/t/pt-query-digest/samples/memc_tcpdump005.txt +++ b/t/pt-query-digest/samples/memc_tcpdump005.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x26193ADA9E14A97E at byte 764 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-06 22:07:14.406827 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump006.txt b/t/pt-query-digest/samples/memc_tcpdump006.txt index 988b8688..04149aa8 100644 --- a/t/pt-query-digest/samples/memc_tcpdump006.txt +++ b/t/pt-query-digest/samples/memc_tcpdump006.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x456F2F160AF2DC0F at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-06 22:07:14.411331 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump007.txt b/t/pt-query-digest/samples/memc_tcpdump007.txt index 93ecfa72..62e20baf 100644 --- a/t/pt-query-digest/samples/memc_tcpdump007.txt +++ b/t/pt-query-digest/samples/memc_tcpdump007.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x28C64E8A71EEAEAF at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-06-11 21:54:49.059144 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump008.txt b/t/pt-query-digest/samples/memc_tcpdump008.txt index 805de0b6..931f13dd 100644 --- a/t/pt-query-digest/samples/memc_tcpdump008.txt +++ b/t/pt-query-digest/samples/memc_tcpdump008.txt @@ -1,8 +1,7 @@ # Query 1: 645.28k QPS, 1.29x concurrency, ID 0x456F2F160AF2DC0F at byte 0 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: |^ | +# Scores: V/M = 0.00 # Time range: 2009-07-06 22:07:14.411331 to 22:07:14.411334 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump009.txt b/t/pt-query-digest/samples/memc_tcpdump009.txt index 44a7a7ae..47340315 100644 --- a/t/pt-query-digest/samples/memc_tcpdump009.txt +++ b/t/pt-query-digest/samples/memc_tcpdump009.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x6A3331FD94A66F54 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-06-11 21:54:52.244534 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/memc_tcpdump010.txt b/t/pt-query-digest/samples/memc_tcpdump010.txt index 32f7de80..ae021d35 100644 --- a/t/pt-query-digest/samples/memc_tcpdump010.txt +++ b/t/pt-query-digest/samples/memc_tcpdump010.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x3D1AED9A2A3A73C8 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-09 22:00:29.066476 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/output_json_slow002.txt b/t/pt-query-digest/samples/output_json_slow002.txt new file mode 100644 index 00000000..f8604c65 --- /dev/null +++ b/t/pt-query-digest/samples/output_json_slow002.txt @@ -0,0 +1,203 @@ + +[ + { + "attributes" : { + "Filesort" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.125, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Filesort_on_disk" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.125, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Full_join" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.125, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Full_scan" : { + "avg" : 1, + "cnt" : 1, + "max" : 1, + "median" : 0, + "min" : 1, + "pct" : 0.125, + "pct_95" : 0, + "stddev" : 0, + "sum" : 1 + }, + "Lock_time" : { + "avg" : "0.000091", + "cnt" : "1.000000", + "max" : "0.000091", + "median" : "0.000091", + "min" : "0.000091", + "pct" : "0.12", + "pct_95" : "0.000091", + "stddev" : 0, + "sum" : "0.000091" + }, + "Merge_passes" : { + "avg" : 0, + "cnt" : "1.000000", + "max" : "0", + "median" : 0, + "min" : "0", + "pct" : "0.12", + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "QC_Hit" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.125, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Query_time" : { + "avg" : "0.726052", + "cnt" : "1.000000", + "max" : "0.726052", + "median" : "0.726052", + "min" : "0.726052", + "pct" : "0.12", + "pct_95" : "0.726052", + "stddev" : 0, + "sum" : "0.726052" + }, + "Rows_examined" : { + "avg" : "62951.000000", + "cnt" : "1.000000", + "max" : "62951.000000", + "median" : "62951.000000", + "min" : "62951.000000", + "pct" : "0.12", + "pct_95" : "62951.000000", + "stddev" : 0, + "sum" : "62951.000000" + }, + "Rows_sent" : { + "avg" : 0, + "cnt" : "1.000000", + "max" : "0", + "median" : 0, + "min" : "0", + "pct" : "0.12", + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Tmp_table" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.125, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Tmp_table_on_disk" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.125, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "bytes" : { + "avg" : "129.000000", + "cnt" : "1.000000", + "max" : "129.000000", + "median" : "129.000000", + "min" : "129.000000", + "pct" : "0.12", + "pct_95" : "129.000000", + "stddev" : 0, + "sum" : "129.000000" + }, + "db" : { + "avg" : 0, + "cnt" : 1, + "max" : "db1", + "median" : 0, + "min" : "db1", + "pct" : 0.142857142857143, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + }, + "host" : { + "avg" : 0, + "cnt" : 1, + "max" : "", + "median" : 0, + "min" : "", + "pct" : 0.125, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + }, + "pos_in_log" : { + "avg" : "338.000000", + "cnt" : "1.000000", + "max" : "338.000000", + "median" : "338.000000", + "min" : "338.000000", + "pct" : "0.12", + "pct_95" : "338.000000", + "stddev" : 0, + "sum" : "338.000000" + }, + "user" : { + "avg" : 0, + "cnt" : 1, + "max" : "[SQL_SLAVE]", + "median" : 0, + "min" : "[SQL_SLAVE]", + "pct" : 0.125, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + } + }, + "class" : { + "checksum" : "66825DDC008FFA89", + "cnt" : 1, + "fingerprint" : "update d?tuningdetail_?_? n inner join d?gonzo a using(gonzo) set n.column? = a.column?, n.word? = a.word?", + "sample" : "update db2.tuningdetail_21_265507 n\n inner join db1.gonzo a using(gonzo) \n set n.column1 = a.column1, n.word3 = a.word3", + "ts_max" : "2007-12-18 11:48:27", + "ts_min" : "2007-12-18 11:48:27" + } + } +] + diff --git a/t/pt-query-digest/samples/output_json_tcpdump021.txt b/t/pt-query-digest/samples/output_json_tcpdump021.txt new file mode 100644 index 00000000..1f5b8826 --- /dev/null +++ b/t/pt-query-digest/samples/output_json_tcpdump021.txt @@ -0,0 +1,359 @@ + +[ + { + "attributes" : { + "Error_no" : { + "avg" : 0, + "cnt" : 1, + "max" : "none", + "median" : 0, + "min" : "none", + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + }, + "No_good_index_used" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "No_index_used" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Query_time" : { + "avg" : "0.000286", + "cnt" : "1.000000", + "max" : "0.000286", + "median" : "0.000286", + "min" : "0.000286", + "pct" : "0.33", + "pct_95" : "0.000286", + "stddev" : 0, + "sum" : "0.000286" + }, + "Rows_affected" : { + "avg" : 0, + "cnt" : "1.000000", + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : "0.33", + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Statement_id" : { + "avg" : 0, + "cnt" : 1, + "max" : 2, + "median" : 0, + "min" : 2, + "pct" : 0.5, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + }, + "Warning_count" : { + "avg" : 0, + "cnt" : "1.000000", + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : "0.33", + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "bytes" : { + "avg" : "35.000000", + "cnt" : "1.000000", + "max" : "35.000000", + "median" : "35.000000", + "min" : "35.000000", + "pct" : "0.33", + "pct_95" : "35.000000", + "stddev" : 0, + "sum" : "35.000000" + }, + "host" : { + "avg" : 0, + "cnt" : 1, + "max" : "127.0.0.1", + "median" : 0, + "min" : "127.0.0.1", + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + }, + "pos_in_log" : { + "avg" : 0, + "cnt" : "1.000000", + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : "0.33", + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + } + }, + "class" : { + "checksum" : "AA8E9FA785927259", + "cnt" : 1, + "fingerprint" : "prepare select i from d.t where i=?", + "sample" : "PREPARE SELECT i FROM d.t WHERE i=?", + "ts_max" : "2009-12-08 09:23:49.637394", + "ts_min" : "2009-12-08 09:23:49.637394" + } + }, + { + "attributes" : { + "Error_no" : { + "avg" : 0, + "cnt" : 1, + "max" : "none", + "median" : 0, + "min" : "none", + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + }, + "No_good_index_used" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "No_index_used" : { + "avg" : 1, + "cnt" : 1, + "max" : 1, + "median" : 0, + "min" : 1, + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : 1 + }, + "Query_time" : { + "avg" : "0.000281", + "cnt" : "1.000000", + "max" : "0.000281", + "median" : "0.000281", + "min" : "0.000281", + "pct" : "0.33", + "pct_95" : "0.000281", + "stddev" : 0, + "sum" : "0.000281" + }, + "Rows_affected" : { + "avg" : 0, + "cnt" : "1.000000", + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : "0.33", + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Statement_id" : { + "avg" : 0, + "cnt" : 1, + "max" : "2", + "median" : 0, + "min" : "2", + "pct" : 0.5, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + }, + "Warning_count" : { + "avg" : 0, + "cnt" : "1.000000", + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : "0.33", + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "bytes" : { + "avg" : "37.000000", + "cnt" : "1.000000", + "max" : "37.000000", + "median" : "37.000000", + "min" : "37.000000", + "pct" : "0.33", + "pct_95" : "37.000000", + "stddev" : 0, + "sum" : "37.000000" + }, + "host" : { + "avg" : 0, + "cnt" : 1, + "max" : "127.0.0.1", + "median" : 0, + "min" : "127.0.0.1", + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + }, + "pos_in_log" : { + "avg" : "1106.000000", + "cnt" : "1.000000", + "max" : "1106.000000", + "median" : "1106.000000", + "min" : "1106.000000", + "pct" : "0.33", + "pct_95" : "1106.000000", + "stddev" : 0, + "sum" : "1106.000000" + } + }, + "class" : { + "checksum" : "3F79759E7FA2F117", + "cnt" : 1, + "fingerprint" : "execute select i from d.t where i=?", + "sample" : "EXECUTE SELECT i FROM d.t WHERE i=\"3\"", + "ts_max" : "2009-12-08 09:23:49.637892", + "ts_min" : "2009-12-08 09:23:49.637892" + } + }, + { + "attributes" : { + "Error_no" : { + "avg" : 0, + "cnt" : 1, + "max" : "none", + "median" : 0, + "min" : "none", + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + }, + "No_good_index_used" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "No_index_used" : { + "avg" : 0, + "cnt" : 1, + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Query_time" : { + "avg" : 0, + "cnt" : "1.000000", + "max" : "0.000000", + "median" : "0.000000", + "min" : "0.000000", + "pct" : "0.33", + "pct_95" : "0.000000", + "stddev" : 0, + "sum" : 0 + }, + "Rows_affected" : { + "avg" : 0, + "cnt" : "1.000000", + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : "0.33", + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "Warning_count" : { + "avg" : 0, + "cnt" : "1.000000", + "max" : 0, + "median" : 0, + "min" : 0, + "pct" : "0.33", + "pct_95" : 0, + "stddev" : 0, + "sum" : 0 + }, + "bytes" : { + "avg" : "27.000000", + "cnt" : "1.000000", + "max" : "27.000000", + "median" : "27.000000", + "min" : "27.000000", + "pct" : "0.33", + "pct_95" : "27.000000", + "stddev" : 0, + "sum" : "27.000000" + }, + "host" : { + "avg" : 0, + "cnt" : 1, + "max" : "127.0.0.1", + "median" : 0, + "min" : "127.0.0.1", + "pct" : 0.333333333333333, + "pct_95" : 0, + "stddev" : 0, + "sum" : null + }, + "pos_in_log" : { + "avg" : "1850.000000", + "cnt" : "1.000000", + "max" : "1850.000000", + "median" : "1850.000000", + "min" : "1850.000000", + "pct" : "0.33", + "pct_95" : "1850.000000", + "stddev" : 0, + "sum" : "1850.000000" + } + }, + "class" : { + "checksum" : "AA353644DE4C4CB4", + "cnt" : 1, + "fingerprint" : "administrator command: Quit", + "sample" : "administrator command: Quit", + "ts_max" : "2009-12-08 09:23:49.638381", + "ts_min" : "2009-12-08 09:23:49.638381" + } + } +] + diff --git a/t/pt-query-digest/samples/pg-sample1 b/t/pt-query-digest/samples/pg-sample1 index 7339202e..d8030e05 100644 --- a/t/pt-query-digest/samples/pg-sample1 +++ b/t/pt-query-digest/samples/pg-sample1 @@ -1,25 +1,25 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x949BAEB72FDE23A2 1.4501 33.3% 16 0.0906 1.00 0.00 SELECT stats_cvs_group -# 2 0x8FFEBD609B778EB2 0.5053 11.6% 45 0.0112 1.00 0.10 INSERT activity_log -# 3 0x64F8E6F000640AF8 0.3750 8.6% 5 0.0750 1.00 0.00 SELECT users -# 4 0x22375E33FDA4E899 0.3705 8.5% 1 0.3705 1.00 0.00 SELECT ONLY OF -# 5 0x60D6962E42C08882 0.1020 2.3% 46 0.0022 1.00 0.00 SELECT plugins -# 6 0x32AF9886FDBBAE30 0.0981 2.3% 38 0.0026 1.00 0.00 SELECT frs_filetype frs_processor frs_file frs_dlstats_filetotal_agg -# 7 0x5E64B4F52EC23D71 0.0936 2.1% 17 0.0055 1.00 0.01 SELECT trove_cat trove_group_link -# 8 0x1929E67B76DC55E7 0.0877 2.0% 5 0.0175 1.00 0.00 SELECT frs_dlstats_grouptotal_vw groups -# 9 0x1451AE69DBB6E0F2 0.0780 1.8% 1 0.0780 1.00 0.00 SELECT users -# 10 0xD7884E7E471BB089 0.0722 1.7% 61 0.0012 1.00 0.00 SELECT forum_group_list_vw -# 11 0x9DBDF5FB59454957 0.0612 1.4% 5 0.0122 1.00 0.00 SELECT users news_bytes groups -# 12 0x834CC93BAA549DD4 0.0609 1.4% 17 0.0036 1.00 0.00 SELECT users user_group -# 13 0xEF691689ACF9DC59 0.0595 1.4% 10 0.0059 1.00 0.00 SELECT frs_package frs_release frs_file groups -# 14 0x10D09F1381004A22 0.0582 1.3% 17 0.0034 1.00 0.00 SELECT groups -# 15 0xCF439D1EC0933550 0.0579 1.3% 2 0.0290 1.00 0.04 SELECT pg_catalog.pg_class pg_catalog.pg_namespace -# 16 0x7D752C8A15925978 0.0544 1.2% 60 0.0009 1.00 0.00 BEGIN SELECT -# 17 0x82AEF03891943FB3 0.0514 1.2% 2 0.0257 1.00 0.03 SELECT forum_group_list_vw -# 18 0x9AA827C1DF73EE43 0.0496 1.1% 17 0.0029 1.00 0.00 SELECT users news_bytes groups -# 19 0x4636BFC0875521C9 0.0447 1.0% 40 0.0011 1.00 0.00 SELECT supported_languages -# 20 0xB1C777CE6EBFE87E 0.0434 1.0% 17 0.0026 1.00 0.00 SELECT frs_package frs_release -# MISC 0xMISC 0.5823 13.4% 334 0.0017 NS 0.0 <47 ITEMS> +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== =============== +# 1 0x949BAEB72FDE23A2 1.4501 33.3% 16 0.0906 0.00 SELECT stats_cvs_group +# 2 0x8FFEBD609B778EB2 0.5053 11.6% 45 0.0112 0.10 INSERT activity_log +# 3 0x64F8E6F000640AF8 0.3750 8.6% 5 0.0750 0.00 SELECT users +# 4 0x22375E33FDA4E899 0.3705 8.5% 1 0.3705 0.00 SELECT ONLY OF +# 5 0x60D6962E42C08882 0.1020 2.3% 46 0.0022 0.00 SELECT plugins +# 6 0x32AF9886FDBBAE30 0.0981 2.3% 38 0.0026 0.00 SELECT frs_filetype frs_processor frs_file frs_dlstats_filetotal_agg +# 7 0x5E64B4F52EC23D71 0.0936 2.1% 17 0.0055 0.01 SELECT trove_cat trove_group_link +# 8 0x1929E67B76DC55E7 0.0877 2.0% 5 0.0175 0.00 SELECT frs_dlstats_grouptotal_vw groups +# 9 0x1451AE69DBB6E0F2 0.0780 1.8% 1 0.0780 0.00 SELECT users +# 10 0xD7884E7E471BB089 0.0722 1.7% 61 0.0012 0.00 SELECT forum_group_list_vw +# 11 0x9DBDF5FB59454957 0.0612 1.4% 5 0.0122 0.00 SELECT users news_bytes groups +# 12 0x834CC93BAA549DD4 0.0609 1.4% 17 0.0036 0.00 SELECT users user_group +# 13 0xEF691689ACF9DC59 0.0595 1.4% 10 0.0059 0.00 SELECT frs_package frs_release frs_file groups +# 14 0x10D09F1381004A22 0.0582 1.3% 17 0.0034 0.00 SELECT groups +# 15 0xCF439D1EC0933550 0.0579 1.3% 2 0.0290 0.04 SELECT pg_catalog.pg_class pg_catalog.pg_namespace +# 16 0x7D752C8A15925978 0.0544 1.2% 60 0.0009 0.00 BEGIN SELECT +# 17 0x82AEF03891943FB3 0.0514 1.2% 2 0.0257 0.03 SELECT forum_group_list_vw +# 18 0x9AA827C1DF73EE43 0.0496 1.1% 17 0.0029 0.00 SELECT users news_bytes groups +# 19 0x4636BFC0875521C9 0.0447 1.0% 40 0.0011 0.00 SELECT supported_languages +# 20 0xB1C777CE6EBFE87E 0.0434 1.0% 17 0.0026 0.00 SELECT frs_package frs_release +# MISC 0xMISC 0.5823 13.4% 334 0.0017 0.0 <47 ITEMS> diff --git a/t/pt-query-digest/samples/pg-syslog-sample1 b/t/pt-query-digest/samples/pg-syslog-sample1 index 8c7f9a5c..ea03c8f7 100644 --- a/t/pt-query-digest/samples/pg-syslog-sample1 +++ b/t/pt-query-digest/samples/pg-syslog-sample1 @@ -1,12 +1,12 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x43088A2EF12EB3EE 0.1661 38.2% 2 0.0830 1.00 0.11 SELECT pg_catalog.pg_class pg_catalog.pg_roles pg_catalog.pg_namespace -# 2 0xD6F2B77706BEEB5F 0.0710 16.3% 1 0.0710 1.00 0.00 SELECT pg_catalog.pg_class pg_catalog.pg_roles pg_catalog.pg_namespace -# 3 0x9213FC20E3993331 0.0464 10.7% 1 0.0464 1.00 0.00 SELECT foo -# 4 0x458CB071ADE822AC 0.0446 10.3% 6 0.0074 1.00 0.00 SELECT -# 5 0x60960AADCFD005F3 0.0426 9.8% 1 0.0426 1.00 0.00 SELECT pg_catalog.pg_class pg_catalog.pg_roles pg_catalog.pg_namespace -# 6 0xA99588746B4C6438 0.0283 6.5% 1 0.0283 1.00 0.00 SELECT pg_catalog.pg_class pg_catalog.pg_roles pg_catalog.pg_namespace -# 7 0x32A1860329937485 0.0278 6.4% 1 0.0278 1.00 0.00 SELECT pg_catalog.pg_database pg_catalog.pg_roles -# MISC 0xMISC 0.0083 1.9% 1 0.0083 NS 0.0 <1 ITEMS> +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== =============== +# 1 0x43088A2EF12EB3EE 0.1661 38.2% 2 0.0830 0.11 SELECT pg_catalog.pg_class pg_catalog.pg_roles pg_catalog.pg_namespace +# 2 0xD6F2B77706BEEB5F 0.0710 16.3% 1 0.0710 0.00 SELECT pg_catalog.pg_class pg_catalog.pg_roles pg_catalog.pg_namespace +# 3 0x9213FC20E3993331 0.0464 10.7% 1 0.0464 0.00 SELECT foo +# 4 0x458CB071ADE822AC 0.0446 10.3% 6 0.0074 0.00 SELECT +# 5 0x60960AADCFD005F3 0.0426 9.8% 1 0.0426 0.00 SELECT pg_catalog.pg_class pg_catalog.pg_roles pg_catalog.pg_namespace +# 6 0xA99588746B4C6438 0.0283 6.5% 1 0.0283 0.00 SELECT pg_catalog.pg_class pg_catalog.pg_roles pg_catalog.pg_namespace +# 7 0x32A1860329937485 0.0278 6.4% 1 0.0278 0.00 SELECT pg_catalog.pg_database pg_catalog.pg_roles +# MISC 0xMISC 0.0083 1.9% 1 0.0083 0.0 <1 ITEMS> diff --git a/t/pt-query-digest/samples/rawlog001.txt b/t/pt-query-digest/samples/rawlog001.txt index 3f298ac0..8227959f 100644 --- a/t/pt-query-digest/samples/rawlog001.txt +++ b/t/pt-query-digest/samples/rawlog001.txt @@ -7,8 +7,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xCB5621E548E5497F at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 50 1 @@ -31,8 +30,7 @@ SELECT c FROM t WHERE id=1\G # Query 2: 0 QPS, 0x concurrency, ID 0x774B2B0B59EBAC2C at byte 27 _______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 50 1 @@ -54,7 +52,7 @@ SELECT c FROM t WHERE id=1\G /* Hello, world! */ SELECT * FROM t2 LIMIT 1\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========= -# 1 0xCB5621E548E5497F 0.0000 0.0% 1 0.0000 1.00 0.00 SELECT t -# 2 0x774B2B0B59EBAC2C 0.0000 0.0% 1 0.0000 1.00 0.00 SELECT t? +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========= +# 1 0xCB5621E548E5497F 0.0000 0.0% 1 0.0000 0.00 SELECT t +# 2 0x774B2B0B59EBAC2C 0.0000 0.0% 1 0.0000 0.00 SELECT t? diff --git a/t/pt-query-digest/samples/slow001_distillreport.txt b/t/pt-query-digest/samples/slow001_distillreport.txt index 02f2165e..757c6152 100644 --- a/t/pt-query-digest/samples/slow001_distillreport.txt +++ b/t/pt-query-digest/samples/slow001_distillreport.txt @@ -5,8 +5,7 @@ # Item 1: 0 QPS, 0x concurrency, ID 0x82E67ABEEDCA3249 at byte 0 _________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -33,8 +32,7 @@ SELECT n # Item 2: 0 QPS, 0x concurrency, ID 0x7AD070CD3F4121D5 at byte 359 _______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:45:10 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow001_report.txt b/t/pt-query-digest/samples/slow001_report.txt index 32440146..d85429cb 100644 --- a/t/pt-query-digest/samples/slow001_report.txt +++ b/t/pt-query-digest/samples/slow001_report.txt @@ -1,7 +1,6 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x7F7D57ACDD8A346E at byte 0 ________ -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -31,8 +30,7 @@ select sleep(2) from n\G # Query 2: 0 QPS, 0x concurrency, ID 0x3A99CC42AEDCCFCD at byte 359 ______ -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:45:10 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow001_select_report.txt b/t/pt-query-digest/samples/slow001_select_report.txt index ae5b49c1..27d29433 100644 --- a/t/pt-query-digest/samples/slow001_select_report.txt +++ b/t/pt-query-digest/samples/slow001_select_report.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x7F7D57ACDD8A346E at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 50 1 @@ -24,8 +23,7 @@ select sleep(2) from n\G # Query 2: 0 QPS, 0x concurrency, ID 0x3A99CC42AEDCCFCD at byte 359 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 50 1 diff --git a/t/pt-query-digest/samples/slow001_tablesreport.txt b/t/pt-query-digest/samples/slow001_tablesreport.txt index 7e92c56b..5dc70bf3 100644 --- a/t/pt-query-digest/samples/slow001_tablesreport.txt +++ b/t/pt-query-digest/samples/slow001_tablesreport.txt @@ -5,8 +5,7 @@ # Item 1: 0.03 QPS, 0.05x concurrency, ID 0x1161D7068EB79526 at byte 0 ___ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-10-15 21:43:52 to 21:45:10 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow002-orderbynonexistent.txt b/t/pt-query-digest/samples/slow002-orderbynonexistent.txt index 96083e5f..b6cc3a83 100644 --- a/t/pt-query-digest/samples/slow002-orderbynonexistent.txt +++ b/t/pt-query-digest/samples/slow002-orderbynonexistent.txt @@ -1,8 +1,7 @@ --order-by attribute Rows_read doesn't exist, using Query_time:sum # Query 1: 0 QPS, 0x concurrency, ID 0x66825DDC008FFA89 at byte 338 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -13,7 +12,6 @@ # Rows examine 100 61.48k 61.48k 61.48k 61.48k 61.48k 0 61.48k # Merge passes 0 0 0 0 0 0 0 0 # Query size 25 129 129 129 129 129 0 129 -# InnoDB: # Boolean: # Full scan 100% yes, 0% no # String: @@ -43,8 +41,7 @@ select n.column1 = a.column1, n.word3 = a.word3 from db2.tuningdetail_21_265507 inner join db1.gonzo a using(gonzo) \G # Query 2: 0 QPS, 0x concurrency, ID 0x0FFE94ABA6A2A9E8 at byte 1334 _____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -86,8 +83,7 @@ WHERE vab3concept1upload='6994465'\G select vab3concept1id = '91848182522' from db4.vab3concept1upload where vab3concept1upload='6994465'\G # Query 3: 0 QPS, 0x concurrency, ID 0xB211BA2B8D6D065C at byte 2393 _____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -128,8 +124,7 @@ SET biz = '91848182522'\G select biz = '91848182522' from foo.bar \G # Query 4: 0 QPS, 0x concurrency, ID 0x6969975466519B81 at byte 2861 _____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -171,8 +166,7 @@ WHERE fillze='899'\G select boop='bop: 899' from bizzle.bat where fillze='899'\G # Query 5: 0 QPS, 0x concurrency, ID 0xC22D235B07D1D774 at byte 1864 _____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -210,8 +204,7 @@ INSERT INTO db1.conch (word3, vid83) VALUES ('211', '18')\G # Query 6: 0 QPS, 0x concurrency, ID 0x7546F89214254F2F at byte 815 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -249,8 +242,7 @@ INSERT INTO db3.vendor11gonzo (makef, bizzle) VALUES ('', 'Exact')\G # Query 7: 0 QPS, 0x concurrency, ID 0x85FFF5AA78E5FF6A at byte 0 ________ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -261,7 +253,6 @@ VALUES ('', 'Exact')\G # Rows examine 0 0 0 0 0 0 0 0 # Merge passes 0 0 0 0 0 0 0 0 # Query size 0 5 5 5 5 5 0 5 -# InnoDB: # String: # Hosts # Users [SQL_SLAVE] diff --git a/t/pt-query-digest/samples/slow002_iters_2.txt b/t/pt-query-digest/samples/slow002_iters_2.txt index 978f6d2d..6bd7c087 100644 --- a/t/pt-query-digest/samples/slow002_iters_2.txt +++ b/t/pt-query-digest/samples/slow002_iters_2.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x66825DDC008FFA89 at byte 338 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -13,7 +12,6 @@ # Rows examine 100 61.48k 61.48k 61.48k 61.48k 61.48k 0 61.48k # Merge passes 0 0 0 0 0 0 0 0 # Query size 25 129 129 129 129 129 0 129 -# InnoDB: # Boolean: # Full scan 100% yes, 0% no # String: @@ -43,7 +41,7 @@ select n.column1 = a.column1, n.word3 = a.word3 from db2.tuningdetail_21_265507 inner join db1.gonzo a using(gonzo) \G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x66825DDC008FFA89 0.7261 95.3% 1 0.7261 1.00 0.00 UPDATE db?.tuningdetail_?_? db?.gonzo -# MISC 0xMISC 0.0360 4.7% 7 0.0051 NS 0.0 <6 ITEMS> +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== =============== +# 1 0x66825DDC008FFA89 0.7261 95.3% 1 0.7261 0.00 UPDATE db?.tuningdetail_?_? db?.gonzo +# MISC 0xMISC 0.0360 4.7% 7 0.0051 0.0 <6 ITEMS> diff --git a/t/pt-query-digest/samples/slow002_orderbyreport.txt b/t/pt-query-digest/samples/slow002_orderbyreport.txt index 1c2c67fe..23cd33f2 100644 --- a/t/pt-query-digest/samples/slow002_orderbyreport.txt +++ b/t/pt-query-digest/samples/slow002_orderbyreport.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xB211BA2B8D6D065C at byte 3374 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -44,8 +43,7 @@ select biz = '91848182522' from foo.bar \G # Query 2: 0 QPS, 0x concurrency, ID 0x66825DDC008FFA89 at byte 338 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -56,7 +54,6 @@ select biz = '91848182522' from foo.bar \G # Rows examine 100 61.48k 61.48k 61.48k 61.48k 61.48k 0 61.48k # Merge passes 0 0 0 0 0 0 0 0 # Query size 25 129 129 129 129 129 0 129 -# InnoDB: # Boolean: # Full scan 100% yes, 0% no # String: diff --git a/t/pt-query-digest/samples/slow002_report.txt b/t/pt-query-digest/samples/slow002_report.txt index 5482aa14..0426d96a 100644 --- a/t/pt-query-digest/samples/slow002_report.txt +++ b/t/pt-query-digest/samples/slow002_report.txt @@ -1,7 +1,6 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x66825DDC008FFA89 at byte 338 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -12,7 +11,6 @@ # Rows examine 100 61.48k 61.48k 61.48k 61.48k 61.48k 0 61.48k # Merge passes 0 0 0 0 0 0 0 0 # Query size 25 129 129 129 129 129 0 129 -# InnoDB: # Boolean: # Full scan 100% yes, 0% no # String: @@ -42,8 +40,7 @@ select n.column1 = a.column1, n.word3 = a.word3 from db2.tuningdetail_21_265507 inner join db1.gonzo a using(gonzo) \G # Query 2: 0 QPS, 0x concurrency, ID 0x0FFE94ABA6A2A9E8 at byte 1334 _____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -85,8 +82,7 @@ WHERE vab3concept1upload='6994465'\G select vab3concept1id = '91848182522' from db4.vab3concept1upload where vab3concept1upload='6994465'\G # Query 3: 0 QPS, 0x concurrency, ID 0xB211BA2B8D6D065C at byte 3374 _____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -127,8 +123,7 @@ SET biz = '91848182522'\G select biz = '91848182522' from foo.bar \G # Query 4: 0 QPS, 0x concurrency, ID 0x6969975466519B81 at byte 2861 _____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -170,8 +165,7 @@ WHERE fillze='899'\G select boop='bop: 899' from bizzle.bat where fillze='899'\G # Query 5: 0 QPS, 0x concurrency, ID 0xC22D235B07D1D774 at byte 1864 _____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -209,8 +203,7 @@ INSERT INTO db1.conch (word3, vid83) VALUES ('211', '18')\G # Query 6: 0 QPS, 0x concurrency, ID 0x7546F89214254F2F at byte 815 ______ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -248,8 +241,7 @@ INSERT INTO db3.vendor11gonzo (makef, bizzle) VALUES ('', 'Exact')\G # Query 7: 0 QPS, 0x concurrency, ID 0x85FFF5AA78E5FF6A at byte 0 ________ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -260,7 +252,6 @@ VALUES ('', 'Exact')\G # Rows examine 0 0 0 0 0 0 0 0 # Merge passes 0 0 0 0 0 0 0 0 # Query size 0 5 5 5 5 5 0 5 -# InnoDB: # String: # Hosts # Users [SQL_SLAVE] diff --git a/t/pt-query-digest/samples/slow002_report_filtered.txt b/t/pt-query-digest/samples/slow002_report_filtered.txt index e9d7411c..294fdd7f 100644 --- a/t/pt-query-digest/samples/slow002_report_filtered.txt +++ b/t/pt-query-digest/samples/slow002_report_filtered.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x6969975466519B81 at byte 2861 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow003_report.txt b/t/pt-query-digest/samples/slow003_report.txt index df294d96..01bb734f 100644 --- a/t/pt-query-digest/samples/slow003_report.txt +++ b/t/pt-query-digest/samples/slow003_report.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x85FFF5AA78E5FF6A at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow004_report.txt b/t/pt-query-digest/samples/slow004_report.txt index c9af29c6..1d44affc 100644 --- a/t/pt-query-digest/samples/slow004_report.txt +++ b/t/pt-query-digest/samples/slow004_report.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xB16C9E5B3D9C484F at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow006-order-by-re.txt b/t/pt-query-digest/samples/slow006-order-by-re.txt index 7df9b322..80e01a69 100644 --- a/t/pt-query-digest/samples/slow006-order-by-re.txt +++ b/t/pt-query-digest/samples/slow006-order-by-re.txt @@ -1,8 +1,7 @@ # Query 1: 0.05 QPS, 0x concurrency, ID 0xA20C29AF174CE545 at byte 1833 __ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:27 to 11:49:30 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -34,8 +33,7 @@ SELECT col FROM foo_tbl\G # Query 2: 0.30 QPS, 0x concurrency, ID 0xD4CD74934382A184 at byte 1469 __ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:57 to 11:49:07 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow006_AR_1.txt b/t/pt-query-digest/samples/slow006_AR_1.txt index dad9c923..481c2715 100644 --- a/t/pt-query-digest/samples/slow006_AR_1.txt +++ b/t/pt-query-digest/samples/slow006_AR_1.txt @@ -1,8 +1,7 @@ # Query 1: 0.05 QPS, 0.00x concurrency, ID 0xA20C29AF174CE545 at byte 1833 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:27 to 11:49:30 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -40,8 +39,7 @@ SELECT col FROM foo_tbl\G # Query 2: 0.30 QPS, 0.00x concurrency, ID 0xD4CD74934382A184 at byte 1469 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:57 to 11:49:07 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow006_AR_2.txt b/t/pt-query-digest/samples/slow006_AR_2.txt index c4338fc7..dac2e8ba 100644 --- a/t/pt-query-digest/samples/slow006_AR_2.txt +++ b/t/pt-query-digest/samples/slow006_AR_2.txt @@ -2,8 +2,7 @@ # Query 2: 0.30 QPS, 0.00x concurrency, ID 0xD4CD74934382A184 at byte 1469 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:57 to 11:49:07 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow006_AR_4.txt b/t/pt-query-digest/samples/slow006_AR_4.txt index 22372b61..fa2361c4 100644 --- a/t/pt-query-digest/samples/slow006_AR_4.txt +++ b/t/pt-query-digest/samples/slow006_AR_4.txt @@ -1,8 +1,7 @@ # Query 1: 0.05 QPS, 0.00x concurrency, ID 0xA20C29AF174CE545 at byte 1833 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:27 to 11:49:30 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -40,8 +39,7 @@ SELECT col FROM foo_tbl\G # Query 2: 0.30 QPS, 0.00x concurrency, ID 0xD4CD74934382A184 at byte 1469 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:57 to 11:49:07 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow006_AR_5.txt b/t/pt-query-digest/samples/slow006_AR_5.txt index 4705e25c..cef99266 100644 --- a/t/pt-query-digest/samples/slow006_AR_5.txt +++ b/t/pt-query-digest/samples/slow006_AR_5.txt @@ -2,8 +2,7 @@ # Query 2: 0.30 QPS, 0.00x concurrency, ID 0xD4CD74934382A184 at byte 1469 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:57 to 11:49:07 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow006_report.txt b/t/pt-query-digest/samples/slow006_report.txt index 76359986..4f5fa94c 100644 --- a/t/pt-query-digest/samples/slow006_report.txt +++ b/t/pt-query-digest/samples/slow006_report.txt @@ -1,8 +1,7 @@ # Query 1: 0.05 QPS, 0.00x concurrency, ID 0xA20C29AF174CE545 at byte 1833 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:27 to 11:49:30 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -34,8 +33,7 @@ SELECT col FROM foo_tbl\G # Query 2: 0.30 QPS, 0.00x concurrency, ID 0xD4CD74934382A184 at byte 1469 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:57 to 11:49:07 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow007_explain_1-51.txt b/t/pt-query-digest/samples/slow007_explain_1-51.txt index 9d37d8c1..2e9c9c61 100644 --- a/t/pt-query-digest/samples/slow007_explain_1-51.txt +++ b/t/pt-query-digest/samples/slow007_explain_1-51.txt @@ -1,9 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x8E306CDB7A800841 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# EXPLAIN sparkline: s -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow007_explain_1-55.txt b/t/pt-query-digest/samples/slow007_explain_1-55.txt index 267ec4c8..a74ee132 100644 --- a/t/pt-query-digest/samples/slow007_explain_1-55.txt +++ b/t/pt-query-digest/samples/slow007_explain_1-55.txt @@ -1,9 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x8E306CDB7A800841 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# EXPLAIN sparkline: I -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow007_explain_1.txt b/t/pt-query-digest/samples/slow007_explain_1.txt index 8bdfeceb..8c2ce5a0 100644 --- a/t/pt-query-digest/samples/slow007_explain_1.txt +++ b/t/pt-query-digest/samples/slow007_explain_1.txt @@ -1,9 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x8E306CDB7A800841 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# EXPLAIN sparkline: s -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow007_explain_2-51.txt b/t/pt-query-digest/samples/slow007_explain_2-51.txt index 4f89e6a1..511c5924 100644 --- a/t/pt-query-digest/samples/slow007_explain_2-51.txt +++ b/t/pt-query-digest/samples/slow007_explain_2-51.txt @@ -1,9 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x8E306CDB7A800841 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# EXPLAIN sparkline: I -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow007_explain_2.txt b/t/pt-query-digest/samples/slow007_explain_2.txt index 17ab592f..3cfac091 100644 --- a/t/pt-query-digest/samples/slow007_explain_2.txt +++ b/t/pt-query-digest/samples/slow007_explain_2.txt @@ -1,9 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x8E306CDB7A800841 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# EXPLAIN sparkline: I -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow007_explain_3.txt b/t/pt-query-digest/samples/slow007_explain_3.txt index 424b6b5f..91235c91 100644 --- a/t/pt-query-digest/samples/slow007_explain_3.txt +++ b/t/pt-query-digest/samples/slow007_explain_3.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x8E306CDB7A800841 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -34,6 +33,6 @@ SELECT fruit FROM trees\G # EXPLAIN failed: DBD::mysql::st execute failed: Table 'food.trees' doesn't exist [for Statement "EXPLAIN /*!50100 PARTITIONS */ SELECT fruit FROM trees"] at line ?. # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M EXPLAIN Item -# ==== ================== ============= ===== ====== ==== ===== ========= ======== -# 1 0x8E306CDB7A800841 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT trees +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ============ +# 1 0x8E306CDB7A800841 0.0000 100.0% 1 0.0000 0.00 SELECT trees diff --git a/t/pt-query-digest/samples/slow007_explain_4.txt b/t/pt-query-digest/samples/slow007_explain_4.txt index e4fe95e8..42013836 100644 --- a/t/pt-query-digest/samples/slow007_explain_4.txt +++ b/t/pt-query-digest/samples/slow007_explain_4.txt @@ -1,5 +1,5 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M EXPLAIN Item -# ==== ================== ============= ===== ====== ==== ===== ======= ========== -# 1 0x8E306CDB7A800841 0.0000 100.0% 1 0.0000 1.00 0.00 I SELECT trees +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ============ +# 1 0x8E306CDB7A800841 0.0000 100.0% 1 0.0000 0.00 SELECT trees diff --git a/t/pt-query-digest/samples/slow008_report.txt b/t/pt-query-digest/samples/slow008_report.txt index e91388f9..f4bb7458 100644 --- a/t/pt-query-digest/samples/slow008_report.txt +++ b/t/pt-query-digest/samples/slow008_report.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xC72BF45D68E35A6E at byte 435 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 33 1 @@ -32,8 +31,7 @@ SELECT MIN(id),MAX(id) FROM tbl\G # Query 2: 0 QPS, 0x concurrency, ID 0xCC47B42511EA22DD at byte 221 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 33 1 @@ -59,8 +57,7 @@ SET NAMES utf8\G # Query 3: 0 QPS, 0x concurrency, ID 0xAA353644DE4C4CB4 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: |^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 33 1 diff --git a/t/pt-query-digest/samples/slow010_reportbyfile.txt b/t/pt-query-digest/samples/slow010_reportbyfile.txt index 2e2d4215..de0b5fa3 100644 --- a/t/pt-query-digest/samples/slow010_reportbyfile.txt +++ b/t/pt-query-digest/samples/slow010_reportbyfile.txt @@ -5,8 +5,7 @@ # Item 1: 0 QPS, 0x concurrency, ID 0xE0976A52E15A18AC at byte 0 _________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow011_report.txt b/t/pt-query-digest/samples/slow011_report.txt index 577ee8b7..d624a280 100644 --- a/t/pt-query-digest/samples/slow011_report.txt +++ b/t/pt-query-digest/samples/slow011_report.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAA353644DE4C4CB4 at byte 435 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.02 -# Query_time sparkline: |^ ^ | +# Scores: V/M = 0.02 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 50 2 @@ -28,8 +27,7 @@ administrator command: Quit\G # Query 2: 0 QPS, 0x concurrency, ID 0xCC47B42511EA22DD at byte 663 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 50 2 diff --git a/t/pt-query-digest/samples/slow013_report.txt b/t/pt-query-digest/samples/slow013_report.txt index 48daf735..3e8d479b 100644 --- a/t/pt-query-digest/samples/slow013_report.txt +++ b/t/pt-query-digest/samples/slow013_report.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x31DA25F95494CA95 at byte 174 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2008-11-27 08:51:20 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -29,8 +28,7 @@ SHOW STATUS\G # Query 2: 0 QPS, 0x concurrency, ID 0x3AEAAD0E15D725B5 at byte 600 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2008-11-27 08:51:21 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -57,8 +55,7 @@ SET autocommit=0\G # Query 3: 0 QPS, 0x concurrency, ID 0x813031B8BBC3B329 at byte 782 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2008-11-27 08:51:21 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -85,8 +82,7 @@ commit\G # Query 4: 0 QPS, 0x concurrency, ID 0xAA353644DE4C4CB4 at byte 385 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: |^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2008-11-27 08:51:21 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow013_report_fingerprint_user.txt b/t/pt-query-digest/samples/slow013_report_fingerprint_user.txt index 01749d56..9ba33aec 100644 --- a/t/pt-query-digest/samples/slow013_report_fingerprint_user.txt +++ b/t/pt-query-digest/samples/slow013_report_fingerprint_user.txt @@ -15,8 +15,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x31DA25F95494CA95 at byte 174 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2008-11-27 08:51:20 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -47,8 +46,7 @@ SHOW STATUS\G # Item 1: 2 QPS, 0.15x concurrency, ID 0x4F1658C9B243995F at byte 174 ____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.15 -# Query_time sparkline: |^ ^ | +# Scores: V/M = 0.15 # Time range: 2008-11-27 08:51:20 to 08:51:21 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow013_report_limit.txt b/t/pt-query-digest/samples/slow013_report_limit.txt index 62f12054..d465694e 100644 --- a/t/pt-query-digest/samples/slow013_report_limit.txt +++ b/t/pt-query-digest/samples/slow013_report_limit.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x31DA25F95494CA95 at byte 174 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2008-11-27 08:51:20 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow013_report_outliers.txt b/t/pt-query-digest/samples/slow013_report_outliers.txt index 0096c271..6b60ddc0 100644 --- a/t/pt-query-digest/samples/slow013_report_outliers.txt +++ b/t/pt-query-digest/samples/slow013_report_outliers.txt @@ -5,8 +5,7 @@ # Item 1: 2 QPS, 0.15x concurrency, ID 0x4F1658C9B243995F at byte 174 ____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.15 -# Query_time sparkline: |^ ^ | +# Scores: V/M = 0.15 # Time range: 2008-11-27 08:51:20 to 08:51:21 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -32,8 +31,7 @@ mytopuser # Item 2: 0 QPS, 0x concurrency, ID 0x8F4C76E92F07EABE at byte 600 _______ # This item is included in the report because it matches --outliers. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2008-11-27 08:51:21 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow013_report_profile.txt b/t/pt-query-digest/samples/slow013_report_profile.txt index 7ace77bd..99245089 100644 --- a/t/pt-query-digest/samples/slow013_report_profile.txt +++ b/t/pt-query-digest/samples/slow013_report_profile.txt @@ -1,8 +1,8 @@ # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x31DA25F95494CA95 0.1494 99.9% 1 0.1494 1.00 0.00 SHOW STATUS -# 2 0x3AEAAD0E15D725B5 0.0001 0.1% 2 0.0000 1.00 0.00 SET -# 3 0x813031B8BBC3B329 0.0000 0.0% 1 0.0000 1.00 0.00 COMMIT -# MISC 0xMISC 0.0000 0.0% 1 0.0000 NS 0.0 <1 ITEMS> +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== =========== +# 1 0x31DA25F95494CA95 0.1494 99.9% 1 0.1494 0.00 SHOW STATUS +# 2 0x3AEAAD0E15D725B5 0.0001 0.1% 2 0.0000 0.00 SET +# 3 0x813031B8BBC3B329 0.0000 0.0% 1 0.0000 0.00 COMMIT +# MISC 0xMISC 0.0000 0.0% 1 0.0000 0.0 <1 ITEMS> diff --git a/t/pt-query-digest/samples/slow013_report_user.txt b/t/pt-query-digest/samples/slow013_report_user.txt index 49f20069..1428d2c5 100644 --- a/t/pt-query-digest/samples/slow013_report_user.txt +++ b/t/pt-query-digest/samples/slow013_report_user.txt @@ -5,8 +5,7 @@ # Item 1: 2 QPS, 0.15x concurrency, ID 0x4F1658C9B243995F at byte 174 ____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.15 -# Query_time sparkline: |^ ^ | +# Scores: V/M = 0.15 # Time range: 2008-11-27 08:51:20 to 08:51:21 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -32,8 +31,7 @@ mytopuser # Item 2: 0 QPS, 0x concurrency, ID 0x8F4C76E92F07EABE at byte 600 _______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2008-11-27 08:51:21 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow014_report.txt b/t/pt-query-digest/samples/slow014_report.txt index 0931345b..dae63fbd 100644 --- a/t/pt-query-digest/samples/slow014_report.txt +++ b/t/pt-query-digest/samples/slow014_report.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x7F7D57ACDD8A346E at byte 1313 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow018_execute_report_1.txt b/t/pt-query-digest/samples/slow018_execute_report_1.txt deleted file mode 100644 index c03e29d7..00000000 --- a/t/pt-query-digest/samples/slow018_execute_report_1.txt +++ /dev/null @@ -1,41 +0,0 @@ - -# Query 1: 0 QPS, 0x concurrency, ID 0x6083030C4A5D8996 at byte 0 ________ -# This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | -# Time range: all events occurred at 2007-10-15 21:43:52 -# Attribute pct total min max avg 95% stddev median -# ============ === ======= ======= ======= ======= ======= ======= ======= -# Count 100 1 -# Exec time 100 2s 2s 2s 2s 2s 0 2s -# Exec orig ti 100 2s 2s 2s 2s 2s 0 2s -# Lock time 0 0 0 0 0 0 0 0 -# Rows sent 100 1 1 1 1 1 0 1 -# Rows examine 0 0 0 0 0 0 0 0 -# Query size 100 44 44 44 44 44 0 44 -# String: -# Hosts localhost -# Users root -# Query_time distribution -# 1us -# 10us -# 100us -# 1ms -# 10ms -# 100ms -# 1s ################################################################ -# 10s+ -# Tables -# SHOW TABLE STATUS LIKE 'foo'\G -# SHOW CREATE TABLE `foo`\G -INSERT INTO `foo` VALUES (1, 2, 3) /*... omitted ...*/\G - -# Statistic Count %/Events -# ====================================== ===== ======== -# events_read 1 100.00 -# events_parsed 1 100.00 -# events_aggregated 1 100.00 -# execute_error 1 100.00 -# execute_executed 1 100.00 -# execute_no_database 1 100.00 -# pipeline_restarted_after_SlowLogParser 1 100.00 diff --git a/t/pt-query-digest/samples/slow018_execute_report_2.txt b/t/pt-query-digest/samples/slow018_execute_report_2.txt deleted file mode 100644 index dc7626a3..00000000 --- a/t/pt-query-digest/samples/slow018_execute_report_2.txt +++ /dev/null @@ -1,30 +0,0 @@ -# Exec orig ti 100 2s 2s 2s 2s 2s 0 2s -# Lock time 0 0 0 0 0 0 0 0 -# Rows sent 100 1 1 1 1 1 0 1 -# Rows examine 0 0 0 0 0 0 0 0 -# Query size 100 44 44 44 44 44 0 44 -# Exec diff ti 100 0 0 0 0 0 0 0 -# String: -# Hosts localhost -# Users root -# Query_time distribution -# 1us -# 10us -# 100us -# 1ms -# 10ms -# 100ms -# 1s -# 10s+ -# Tables -# SHOW TABLE STATUS LIKE 'foo'\G -# SHOW CREATE TABLE `foo`\G -INSERT INTO `foo` VALUES (1, 2, 3) /*... omitted ...*/\G - -# Statistic Count %/Events -# ====================================== ===== ======== -# events_read 1 100.00 -# events_parsed 1 100.00 -# events_aggregated 1 100.00 -# execute_executed 1 100.00 -# pipeline_restarted_after_SlowLogParser 1 100.00 diff --git a/t/pt-query-digest/samples/slow018_report.txt b/t/pt-query-digest/samples/slow018_report.txt index 61fc6497..a24e59af 100644 --- a/t/pt-query-digest/samples/slow018_report.txt +++ b/t/pt-query-digest/samples/slow018_report.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x6083030C4A5D8996 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow019_report.txt b/t/pt-query-digest/samples/slow019_report.txt index ba1fbb6c..2ae61093 100644 --- a/t/pt-query-digest/samples/slow019_report.txt +++ b/t/pt-query-digest/samples/slow019_report.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAA353644DE4C4CB4 at byte 435 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.02 -# Query_time sparkline: |^ ^ | +# Scores: V/M = 0.02 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 66 2 @@ -28,8 +27,7 @@ administrator command: Quit\G # Query 2: 0 QPS, 0x concurrency, ID 0xCC47B42511EA22DD at byte 221 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 33 1 diff --git a/t/pt-query-digest/samples/slow019_report_noza.txt b/t/pt-query-digest/samples/slow019_report_noza.txt index 634bc105..fb1683d8 100644 --- a/t/pt-query-digest/samples/slow019_report_noza.txt +++ b/t/pt-query-digest/samples/slow019_report_noza.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAA353644DE4C4CB4 at byte 435 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.02 -# Query_time sparkline: |^ ^ | +# Scores: V/M = 0.02 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 66 2 @@ -28,8 +27,7 @@ administrator command: Quit\G # Query 2: 0 QPS, 0x concurrency, ID 0xCC47B42511EA22DD at byte 221 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 33 1 diff --git a/t/pt-query-digest/samples/slow020_table_access.txt b/t/pt-query-digest/samples/slow020_table_access.txt deleted file mode 100644 index 4b11cac7..00000000 --- a/t/pt-query-digest/samples/slow020_table_access.txt +++ /dev/null @@ -1,3 +0,0 @@ -read `db2`.`foo` -write `db`.`tbl` -read `db1`.`foo` diff --git a/t/pt-query-digest/samples/slow023.txt b/t/pt-query-digest/samples/slow023.txt index 34b1e13a..ae3db272 100644 --- a/t/pt-query-digest/samples/slow023.txt +++ b/t/pt-query-digest/samples/slow023.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x8E38374648788E52 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow024.txt b/t/pt-query-digest/samples/slow024.txt index 1f97fb73..4bc6fe2c 100644 --- a/t/pt-query-digest/samples/slow024.txt +++ b/t/pt-query-digest/samples/slow024.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x93E5C17055D970BE at byte 514419 ___ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -31,8 +30,7 @@ INSERT INTO `film_actor` VALUES (1,1,'2006-02-15 10:05:03') /*... omitted ...*/O # Query 2: 0 QPS, 0x concurrency, ID 0xA1C3EE4F5996E672 at byte 342942 ___ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -61,8 +59,7 @@ INSERT IGNORE INTO `film_actor` VALUES (1,1,'2006-02-15 10:05:03') /*... omitted # Query 3: 0 QPS, 0x concurrency, ID 0xA2C576176F348267 at byte 171471 ___ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow028.txt b/t/pt-query-digest/samples/slow028.txt index bc8735e9..d0f27025 100644 --- a/t/pt-query-digest/samples/slow028.txt +++ b/t/pt-query-digest/samples/slow028.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x182FF6A853858893 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-10-15 21:43:52 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow030_table_access.txt b/t/pt-query-digest/samples/slow030_table_access.txt deleted file mode 100644 index 3e8364d9..00000000 --- a/t/pt-query-digest/samples/slow030_table_access.txt +++ /dev/null @@ -1,2 +0,0 @@ -read `foo` -read `bar` diff --git a/t/pt-query-digest/samples/slow032.txt b/t/pt-query-digest/samples/slow032.txt index e9eb9152..18c3f306 100644 --- a/t/pt-query-digest/samples/slow032.txt +++ b/t/pt-query-digest/samples/slow032.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x7546F89214254F2F at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 100 1 diff --git a/t/pt-query-digest/samples/slow033-precise-since-until.txt b/t/pt-query-digest/samples/slow033-precise-since-until.txt index 379a99d1..f036f4cf 100644 --- a/t/pt-query-digest/samples/slow033-precise-since-until.txt +++ b/t/pt-query-digest/samples/slow033-precise-since-until.txt @@ -1,8 +1,7 @@ # Query 1: 2 QPS, 0.00x concurrency, ID 0x07AEF8EFAB3FA3CE at byte 509 ___ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-07-27 11:19:30 to 11:19:31 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -33,8 +32,7 @@ SELECT * FROM bar\G # Query 2: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 179 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-26 11:19:28 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow033-rtm-event-1h.txt b/t/pt-query-digest/samples/slow033-rtm-event-1h.txt index 6fd36a99..473568ef 100644 --- a/t/pt-query-digest/samples/slow033-rtm-event-1h.txt +++ b/t/pt-query-digest/samples/slow033-rtm-event-1h.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-25 11:19:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -32,6 +31,6 @@ SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo diff --git a/t/pt-query-digest/samples/slow033-rtm-event-25h.txt b/t/pt-query-digest/samples/slow033-rtm-event-25h.txt index 5b74d609..7b70d373 100644 --- a/t/pt-query-digest/samples/slow033-rtm-event-25h.txt +++ b/t/pt-query-digest/samples/slow033-rtm-event-25h.txt @@ -1,8 +1,7 @@ # Query 1: 0.00 QPS, 0.00x concurrency, ID 0xAC1BF726F2AB10C5 at byte 179 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-07-25 11:19:27 to 2009-07-26 11:19:28 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -32,6 +31,6 @@ SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 2 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 2 0.0000 0.00 SELECT foo diff --git a/t/pt-query-digest/samples/slow033-rtm-interval-1d.txt b/t/pt-query-digest/samples/slow033-rtm-interval-1d.txt index 5f652dba..076011a9 100644 --- a/t/pt-query-digest/samples/slow033-rtm-interval-1d.txt +++ b/t/pt-query-digest/samples/slow033-rtm-interval-1d.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-25 11:19:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -32,14 +31,13 @@ SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 179 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-26 11:19:28 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -69,14 +67,13 @@ SELECT * FROM foo\G SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo # Query 1: 2 QPS, 0.00x concurrency, ID 0x07AEF8EFAB3FA3CE at byte 509 ___ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-07-27 11:19:30 to 11:19:31 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -107,8 +104,7 @@ SELECT * FROM bar\G # Query 2: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 683 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-27 11:30:00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -138,15 +134,14 @@ SELECT * FROM bar\G SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x07AEF8EFAB3FA3CE 0.0000 66.7% 2 0.0000 1.00 0.00 SELECT bar -# 2 0xAC1BF726F2AB10C5 0.0000 33.3% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0x07AEF8EFAB3FA3CE 0.0000 66.7% 2 0.0000 0.00 SELECT bar +# 2 0xAC1BF726F2AB10C5 0.0000 33.3% 1 0.0000 0.00 SELECT foo # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 861 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-28 18:00:00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -176,6 +171,6 @@ SELECT * FROM foo\G SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo diff --git a/t/pt-query-digest/samples/slow033-rtm-interval-30m.txt b/t/pt-query-digest/samples/slow033-rtm-interval-30m.txt index 3243cf0e..5bab12fe 100644 --- a/t/pt-query-digest/samples/slow033-rtm-interval-30m.txt +++ b/t/pt-query-digest/samples/slow033-rtm-interval-30m.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-25 11:19:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -32,14 +31,13 @@ SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 179 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-26 11:19:28 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -69,14 +67,13 @@ SELECT * FROM foo\G SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo # Query 1: 2 QPS, 0.00x concurrency, ID 0x07AEF8EFAB3FA3CE at byte 509 ___ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-07-27 11:19:30 to 11:19:31 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -106,14 +103,13 @@ SELECT * FROM foo\G SELECT * FROM bar\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x07AEF8EFAB3FA3CE 0.0000 100.0% 2 0.0000 1.00 0.00 SELECT bar +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0x07AEF8EFAB3FA3CE 0.0000 100.0% 2 0.0000 0.00 SELECT bar # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 683 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-27 11:30:00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -143,14 +139,13 @@ SELECT * FROM bar\G SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 861 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-28 18:00:00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -180,6 +175,6 @@ SELECT * FROM foo\G SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo diff --git a/t/pt-query-digest/samples/slow033-rtm-interval-30s-3iter.txt b/t/pt-query-digest/samples/slow033-rtm-interval-30s-3iter.txt index 7d406587..c4d782bb 100644 --- a/t/pt-query-digest/samples/slow033-rtm-interval-30s-3iter.txt +++ b/t/pt-query-digest/samples/slow033-rtm-interval-30s-3iter.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-25 11:19:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -32,14 +31,13 @@ SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 179 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-26 11:19:28 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -69,14 +67,13 @@ SELECT * FROM foo\G SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo # Query 1: 0 QPS, 0x concurrency, ID 0x07AEF8EFAB3FA3CE at byte 344 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-27 11:19:30 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -106,6 +103,6 @@ SELECT * FROM foo\G SELECT * FROM bar\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x07AEF8EFAB3FA3CE 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT bar +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0x07AEF8EFAB3FA3CE 0.0000 100.0% 1 0.0000 0.00 SELECT bar diff --git a/t/pt-query-digest/samples/slow033-rtm-interval-30s.txt b/t/pt-query-digest/samples/slow033-rtm-interval-30s.txt index 9a101610..24839a2d 100644 --- a/t/pt-query-digest/samples/slow033-rtm-interval-30s.txt +++ b/t/pt-query-digest/samples/slow033-rtm-interval-30s.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-25 11:19:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -32,14 +31,13 @@ SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 179 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-26 11:19:28 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -69,14 +67,13 @@ SELECT * FROM foo\G SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo # Query 1: 0 QPS, 0x concurrency, ID 0x07AEF8EFAB3FA3CE at byte 344 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-27 11:19:30 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -106,14 +103,13 @@ SELECT * FROM foo\G SELECT * FROM bar\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x07AEF8EFAB3FA3CE 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT bar +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0x07AEF8EFAB3FA3CE 0.0000 100.0% 1 0.0000 0.00 SELECT bar # Query 1: 0 QPS, 0x concurrency, ID 0x07AEF8EFAB3FA3CE at byte 509 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-27 11:19:31 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -143,14 +139,13 @@ SELECT * FROM bar\G SELECT * FROM bar\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x07AEF8EFAB3FA3CE 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT bar +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0x07AEF8EFAB3FA3CE 0.0000 100.0% 1 0.0000 0.00 SELECT bar # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 683 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-27 11:30:00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -180,14 +175,13 @@ SELECT * FROM bar\G SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 861 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-28 18:00:00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -217,6 +211,6 @@ SELECT * FROM foo\G SELECT * FROM foo\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 1.00 0.00 SELECT foo +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAC1BF726F2AB10C5 0.0000 100.0% 1 0.0000 0.00 SELECT foo diff --git a/t/pt-query-digest/samples/slow033-since-Nd.txt b/t/pt-query-digest/samples/slow033-since-Nd.txt index d196607b..024db278 100644 --- a/t/pt-query-digest/samples/slow033-since-Nd.txt +++ b/t/pt-query-digest/samples/slow033-since-Nd.txt @@ -1,8 +1,7 @@ # Query 1: 0.00 QPS, 0.00x concurrency, ID 0xAC1BF726F2AB10C5 at byte 861 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-07-25 11:19:27 to 2009-07-28 18:00:00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -33,8 +32,7 @@ SELECT * FROM foo\G # Query 2: 2 QPS, 0.00x concurrency, ID 0x07AEF8EFAB3FA3CE at byte 509 ___ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-07-27 11:19:30 to 11:19:31 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow033-since-yymmdd.txt b/t/pt-query-digest/samples/slow033-since-yymmdd.txt index bb2c52e7..21f1cc67 100644 --- a/t/pt-query-digest/samples/slow033-since-yymmdd.txt +++ b/t/pt-query-digest/samples/slow033-since-yymmdd.txt @@ -1,8 +1,7 @@ # Query 1: 2 QPS, 0.00x concurrency, ID 0x07AEF8EFAB3FA3CE at byte 509 ___ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-07-27 11:19:30 to 11:19:31 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -33,8 +32,7 @@ SELECT * FROM bar\G # Query 2: 0.00 QPS, 0.00x concurrency, ID 0xAC1BF726F2AB10C5 at byte 861 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-07-27 11:30:00 to 2009-07-28 18:00:00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow033-since-yyyy-mm-dd.txt b/t/pt-query-digest/samples/slow033-since-yyyy-mm-dd.txt index 169a3421..4e0d2d2a 100644 --- a/t/pt-query-digest/samples/slow033-since-yyyy-mm-dd.txt +++ b/t/pt-query-digest/samples/slow033-since-yyyy-mm-dd.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAC1BF726F2AB10C5 at byte 861 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-07-28 18:00:00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow033-until-date.txt b/t/pt-query-digest/samples/slow033-until-date.txt index cd331351..26373f79 100644 --- a/t/pt-query-digest/samples/slow033-until-date.txt +++ b/t/pt-query-digest/samples/slow033-until-date.txt @@ -1,8 +1,7 @@ # Query 1: 0.00 QPS, 0.00x concurrency, ID 0xAC1BF726F2AB10C5 at byte 179 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-07-25 11:19:27 to 2009-07-26 11:19:28 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow034-order-by-Locktime-sum-with-Locktime-distro.txt b/t/pt-query-digest/samples/slow034-order-by-Locktime-sum-with-Locktime-distro.txt index f108bdec..d861d638 100644 --- a/t/pt-query-digest/samples/slow034-order-by-Locktime-sum-with-Locktime-distro.txt +++ b/t/pt-query-digest/samples/slow034-order-by-Locktime-sum-with-Locktime-distro.txt @@ -1,7 +1,6 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xABE9508269335CD1 at byte 1866 _____ -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Lock_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-08-05 13:00:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -38,8 +37,7 @@ DELETE FROM forest WHERE animal = 'dead'\G select * from forest WHERE animal = 'dead'\G # Query 2: 0.00 QPS, 0.00x concurrency, ID 0xAC1BF726F2AB10C5 at byte 934 -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.03 -# Lock_time sparkline: | _^ | +# Scores: V/M = 0.03 # Time range: 2009-08-05 11:00:27 to 13:00:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -71,8 +69,7 @@ select * from forest WHERE animal = 'dead'\G SELECT * FROM foo\G # Query 3: 0 QPS, 0x concurrency, ID 0xB79802214165F670 at byte 1267 _____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.73 -# Lock_time sparkline: | ^^ | +# Scores: V/M = 0.73 # Time range: all events occurred at 2009-08-05 12:00:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -102,8 +99,7 @@ SELECT * FROM foo\G INSERT INTO tbl VALUES ('a', 'b')\G # Query 4: 0 QPS, 0x concurrency, ID 0x1F9B2F47A843D460 at byte 333 ______ -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Lock_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-08-05 11:00:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -132,8 +128,7 @@ INSERT INTO tbl VALUES ('a', 'b')\G SELECT id FROM tbl WHERE id = 1\G # Query 5: 0 QPS, 0x concurrency, ID 0x3F1024B96D9D469E at byte 625 ______ -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Lock_time sparkline: |^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-08-05 11:00:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -166,10 +161,10 @@ SELECT id FROM tbl WHERE id = 1\G SELECT COUNT(*) FROM blah WHERE col > 2\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== =============== ===== ========= ==== ===== ===== -# 1 0xABE9508269335CD1 1349.0001 98.9% 1 1349.0001 0.00 0.00 DELETE forest -# 2 0xAC1BF726F2AB10C5 2.9042 0.2% 4 0.7261 1.00 0.03 SELECT foo -# 3 0xB79802214165F670 0.7261 0.1% 2 0.3631 1.00 0.73 INSERT tbl -# 4 0x1F9B2F47A843D460 1.7261 0.1% 1 1.7261 0.50 0.00 SELECT tbl -# 5 0x3F1024B96D9D469E 9.0001 0.7% 1 9.0001 0.00 0.00 SELECT blah +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== =============== ===== ========= ===== ========== +# 1 0xABE9508269335CD1 1349.0001 98.9% 1 1349.0001 0.00 DELETE forest +# 2 0xAC1BF726F2AB10C5 2.9042 0.2% 4 0.7261 0.03 SELECT foo +# 3 0xB79802214165F670 0.7261 0.1% 2 0.3631 0.73 INSERT tbl +# 4 0x1F9B2F47A843D460 1.7261 0.1% 1 1.7261 0.00 SELECT tbl +# 5 0x3F1024B96D9D469E 9.0001 0.7% 1 9.0001 0.00 SELECT blah diff --git a/t/pt-query-digest/samples/slow034-order-by-Locktime-sum.txt b/t/pt-query-digest/samples/slow034-order-by-Locktime-sum.txt index 39c0d365..56feb2ef 100644 --- a/t/pt-query-digest/samples/slow034-order-by-Locktime-sum.txt +++ b/t/pt-query-digest/samples/slow034-order-by-Locktime-sum.txt @@ -1,7 +1,6 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xABE9508269335CD1 at byte 1866 _____ -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-08-05 13:00:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -38,8 +37,7 @@ DELETE FROM forest WHERE animal = 'dead'\G select * from forest WHERE animal = 'dead'\G # Query 2: 0.00 QPS, 0.00x concurrency, ID 0xAC1BF726F2AB10C5 at byte 934 -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.03 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.03 # Time range: 2009-08-05 11:00:27 to 13:00:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -71,8 +69,7 @@ select * from forest WHERE animal = 'dead'\G SELECT * FROM foo\G # Query 3: 0 QPS, 0x concurrency, ID 0xB79802214165F670 at byte 1267 _____ -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.73 -# Query_time sparkline: | ^ ^ | +# Scores: V/M = 0.73 # Time range: all events occurred at 2009-08-05 12:00:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -102,8 +99,7 @@ SELECT * FROM foo\G INSERT INTO tbl VALUES ('a', 'b')\G # Query 4: 0 QPS, 0x concurrency, ID 0x1F9B2F47A843D460 at byte 333 ______ -# Scores: Apdex = 0.50 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-08-05 11:00:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -132,8 +128,7 @@ INSERT INTO tbl VALUES ('a', 'b')\G SELECT id FROM tbl WHERE id = 1\G # Query 5: 0 QPS, 0x concurrency, ID 0x3F1024B96D9D469E at byte 625 ______ -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-08-05 11:00:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -166,10 +161,10 @@ SELECT id FROM tbl WHERE id = 1\G SELECT COUNT(*) FROM blah WHERE col > 2\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== =============== ===== ========= ==== ===== ===== -# 1 0xABE9508269335CD1 1349.0001 98.9% 1 1349.0001 0.00 0.00 DELETE forest -# 2 0xAC1BF726F2AB10C5 2.9042 0.2% 4 0.7261 1.00 0.03 SELECT foo -# 3 0xB79802214165F670 0.7261 0.1% 2 0.3631 1.00 0.73 INSERT tbl -# 4 0x1F9B2F47A843D460 1.7261 0.1% 1 1.7261 0.50 0.00 SELECT tbl -# 5 0x3F1024B96D9D469E 9.0001 0.7% 1 9.0001 0.00 0.00 SELECT blah +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== =============== ===== ========= ===== ========== +# 1 0xABE9508269335CD1 1349.0001 98.9% 1 1349.0001 0.00 DELETE forest +# 2 0xAC1BF726F2AB10C5 2.9042 0.2% 4 0.7261 0.03 SELECT foo +# 3 0xB79802214165F670 0.7261 0.1% 2 0.3631 0.73 INSERT tbl +# 4 0x1F9B2F47A843D460 1.7261 0.1% 1 1.7261 0.00 SELECT tbl +# 5 0x3F1024B96D9D469E 9.0001 0.7% 1 9.0001 0.00 SELECT blah diff --git a/t/pt-query-digest/samples/slow035.txt b/t/pt-query-digest/samples/slow035.txt index e1262170..c337879d 100644 --- a/t/pt-query-digest/samples/slow035.txt +++ b/t/pt-query-digest/samples/slow035.txt @@ -19,8 +19,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x727841EC88423713 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -57,8 +56,7 @@ INSERT INTO db.v (m, b) VALUES ('', 'Exact')\G # Query 2: 0 QPS, 0x concurrency, ID 0x9E892D4B16D7BFC2 at byte 525 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -68,7 +66,6 @@ INSERT INTO db.v (m, b) VALUES ('', 'Exact')\G # Rows sent 0 0 0 0 0 0 0 0 # Rows examine 0 0 0 0 0 0 0 0 # Query size 52 48 48 48 48 48 0 48 -# InnoDB: # String: # Hosts # Users [SQL_SLAVE] @@ -88,7 +85,7 @@ INSERT INTO db.v (m, b) VALUES ('', 'Exact')\G SELECT * FROM blah WHERE something = 'important'\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x727841EC88423713 0.0000 0.0% 1 0.0000 1.00 0.00 INSERT db.v -# 2 0x9E892D4B16D7BFC2 0.0000 0.0% 1 0.0000 1.00 0.00 SELECT blah +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== =========== +# 1 0x727841EC88423713 0.0000 0.0% 1 0.0000 0.00 INSERT db.v +# 2 0x9E892D4B16D7BFC2 0.0000 0.0% 1 0.0000 0.00 SELECT blah diff --git a/t/pt-query-digest/samples/slow037_report.txt b/t/pt-query-digest/samples/slow037_report.txt index ef75bee9..ee1fe919 100644 --- a/t/pt-query-digest/samples/slow037_report.txt +++ b/t/pt-query-digest/samples/slow037_report.txt @@ -5,8 +5,7 @@ # Item 1: 0 QPS, 0x concurrency, ID 0xABCC9DEC8C43EEDC at byte 0 _________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2007-12-18 11:48:27 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -28,6 +27,6 @@ LOCK foo bar # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ======== ============= ===== ====== ==== ===== ============ -# 1 0x 0.0010 100.0% 1 0.0010 1.00 0.00 LOCK foo bar +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ======== ============= ===== ====== ===== ============ +# 1 0x 0.0010 100.0% 1 0.0010 0.00 LOCK foo bar diff --git a/t/pt-query-digest/samples/slow042-show-all-host.txt b/t/pt-query-digest/samples/slow042-show-all-host.txt index 3fcf79c3..fe9f56dc 100644 --- a/t/pt-query-digest/samples/slow042-show-all-host.txt +++ b/t/pt-query-digest/samples/slow042-show-all-host.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x7CE9953EA3A36141 at byte 417 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-05 19:55:11 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow042.txt b/t/pt-query-digest/samples/slow042.txt index 89616f51..bee41e47 100644 --- a/t/pt-query-digest/samples/slow042.txt +++ b/t/pt-query-digest/samples/slow042.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x7CE9953EA3A36141 at byte 417 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-05 19:55:11 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow048.txt b/t/pt-query-digest/samples/slow048.txt index 3213fa47..efa2cae1 100644 --- a/t/pt-query-digest/samples/slow048.txt +++ b/t/pt-query-digest/samples/slow048.txt @@ -1,8 +1,7 @@ # Query 1: 1.33 QPS, 0.00x concurrency, ID 0x208AC308FD716D83 at byte 454 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2010-06-24 11:48:27 to 11:48:30 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -28,6 +27,6 @@ SELECT * FROM `products` ORDER BY name, shape asc\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x208AC308FD716D83 0.0001 100.0% 4 0.0000 1.00 0.00 SELECT products +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== =============== +# 1 0x208AC308FD716D83 0.0001 100.0% 4 0.0000 0.00 SELECT products diff --git a/t/pt-query-digest/samples/slow049.txt b/t/pt-query-digest/samples/slow049.txt index e469e0ac..290045e5 100644 --- a/t/pt-query-digest/samples/slow049.txt +++ b/t/pt-query-digest/samples/slow049.txt @@ -10,17 +10,16 @@ # Query size 308 30 34 30.80 31.70 1.64 28.75 # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== =============== ===== ======== ==== ===== ====== -# 1 0x95AADD230F4EB56A 1000.0000 53.8% 2 500.0000 0.00 0.00 SELECT two -# 2 0x5081E1858C60FD05 500.0000 26.9% 1 500.0000 0.00 0.00 SELECT three -# 4 0x70E215C4BFED0080 50.0000 2.7% 5 10.0000 0.00 0.00 SELECT one -# MISC 0xMISC 310.0000 16.7% 2 155.0000 NS 0.0 <2 ITEMS> +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== =============== ===== ======== ===== =========== +# 1 0x95AADD230F4EB56A 1000.0000 53.8% 2 500.0000 0.00 SELECT two +# 2 0x5081E1858C60FD05 500.0000 26.9% 1 500.0000 0.00 SELECT three +# 4 0x70E215C4BFED0080 50.0000 2.7% 5 10.0000 0.00 SELECT one +# MISC 0xMISC 310.0000 16.7% 2 155.0000 0.0 <2 ITEMS> # Query 1: 2 QPS, 1.00kx concurrency, ID 0x95AADD230F4EB56A at byte 886 __ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: 2010-06-24 11:48:34 to 11:48:35 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -47,8 +46,7 @@ SELECT two FROM two WHERE id=?\G # Query 2: 0 QPS, 0x concurrency, ID 0x5081E1858C60FD05 at byte 1013 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: all events occurred at 2010-06-24 11:48:35 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -75,8 +73,7 @@ SELECT three FROM three WHERE id=?\G # Query 4: 1.25 QPS, 12.50x concurrency, ID 0x70E215C4BFED0080 at byte 633 # This item is included in the report because it matches --outliers. -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: 2010-06-24 11:48:21 to 11:48:25 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow050.txt b/t/pt-query-digest/samples/slow050.txt index 052c252b..594a7458 100644 --- a/t/pt-query-digest/samples/slow050.txt +++ b/t/pt-query-digest/samples/slow050.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x305E73C51188758F at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^| +# Scores: V/M = 0.00 # Time range: all events occurred at 2010-06-24 11:48:00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -29,6 +28,6 @@ UPDATE mybbl_MBMessage SET groupId = (select groupId from Group_ where name = 'Guest')\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============== ===== ======= ==== ===== ======== -# 1 0x305E73C51188758F 10.0000 100.0% 1 10.0000 0.00 0.00 UPDATE SELECT mybbl_MBMessage Group_ +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============== ===== ======= ===== ============= +# 1 0x305E73C51188758F 10.0000 100.0% 1 10.0000 0.00 UPDATE SELECT mybbl_MBMessage Group_ diff --git a/t/pt-query-digest/samples/slow051.txt b/t/pt-query-digest/samples/slow051.txt index be391ce9..d96d69c2 100644 --- a/t/pt-query-digest/samples/slow051.txt +++ b/t/pt-query-digest/samples/slow051.txt @@ -1,8 +1,7 @@ # Query 1: 0.20 QPS, 0.00x concurrency, ID 0xD989521B246E945B at byte 146 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2007-12-18 11:48:27 to 11:48:37 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -27,6 +26,6 @@ LOAD DATA INFILE '/tmp/bar.txt' INTO db.tbl\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ====== -# 1 0xD989521B246E945B 0.0000 100.0% 2 0.0000 1.00 0.00 db.tbl +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ====== +# 1 0xD989521B246E945B 0.0000 100.0% 2 0.0000 0.00 db.tbl diff --git a/t/pt-query-digest/samples/slow052-apdex-t-0.1.txt b/t/pt-query-digest/samples/slow052-apdex-t-0.1.txt deleted file mode 100644 index da8b2774..00000000 --- a/t/pt-query-digest/samples/slow052-apdex-t-0.1.txt +++ /dev/null @@ -1,66 +0,0 @@ - -# Query 1: 0 QPS, 0x concurrency, ID 0x32B0659E6D13E5A2 at byte 16849 ____ -# This item is included in the report because it matches --limit. -# Scores: Apdex = 0.00 [0.1], V/M = 0.48 -# Query_time sparkline: | ^ | -# Attribute pct total min max avg 95% stddev median -# ============ === ======= ======= ======= ======= ======= ======= ======= -# Count 50 100 -# Exec time 74 308s 1s 5s 3s 5s 1s 3s -# Lock time 0 0 0 0 0 0 0 0 -# Rows sent 50 100 1 1 1 1 0 1 -# Rows examine 0 0 0 0 0 0 0 0 -# Query size 51 4.59k 47 47 47 47 0 47 -# String: -# Hosts localhost -# Users root -# Query_time distribution -# 1us -# 10us -# 100us -# 1ms -# 10ms -# 100ms -# 1s ################################################################ -# 10s+ -# Tables -# SHOW TABLE STATUS LIKE 'unsteady_table'\G -# SHOW CREATE TABLE `unsteady_table`\G -# EXPLAIN /*!50100 PARTITIONS*/ -select very_variable_column from unsteady_table\G - -# Query 2: 0 QPS, 0x concurrency, ID 0x2F621C2B0611518C at byte 8582 _____ -# This item is included in the report because it matches --limit. -# Scores: Apdex = 0.00 [0.1], V/M = 0.00 -# Query_time sparkline: | ^ | -# Attribute pct total min max avg 95% stddev median -# ============ === ======= ======= ======= ======= ======= ======= ======= -# Count 50 100 -# Exec time 25 105s 1s 1s 1s 1s 30ms 1s -# Lock time 0 0 0 0 0 0 0 0 -# Rows sent 50 100 1 1 1 1 0 1 -# Rows examine 0 0 0 0 0 0 0 0 -# Query size 48 4.39k 45 45 45 45 0 45 -# String: -# Hosts localhost -# Users root -# Query_time distribution -# 1us -# 10us -# 100us -# 1ms -# 10ms -# 100ms -# 1s ################################################################ -# 10s+ -# Tables -# SHOW TABLE STATUS LIKE 'steady_table'\G -# SHOW CREATE TABLE `steady_table`\G -# EXPLAIN /*!50100 PARTITIONS*/ -select less_variable_column from steady_table\G - -# Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============== ===== ====== ==== ===== ========= -# 1 0x32B0659E6D13E5A2 308.4675 74.6% 100 3.0847 0.00 0.48 SELECT unsteady_table -# 2 0x2F621C2B0611518C 104.9344 25.4% 100 1.0493 0.00 0.00 SELECT steady_table diff --git a/t/pt-query-digest/samples/slow052.txt b/t/pt-query-digest/samples/slow052.txt index 5827481f..92214103 100644 --- a/t/pt-query-digest/samples/slow052.txt +++ b/t/pt-query-digest/samples/slow052.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x32B0659E6D13E5A2 at byte 16849 ____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.38 [1.0], V/M = 0.48 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.48 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 50 100 @@ -31,8 +30,7 @@ select very_variable_column from unsteady_table\G # Query 2: 0 QPS, 0x concurrency, ID 0x2F621C2B0611518C at byte 8582 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 0.72 [1.0], V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 50 100 @@ -60,7 +58,7 @@ select very_variable_column from unsteady_table\G select less_variable_column from steady_table\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============== ===== ====== ==== ===== ========= -# 1 0x32B0659E6D13E5A2 308.4675 74.6% 100 3.0847 0.38 0.48 SELECT unsteady_table -# 2 0x2F621C2B0611518C 104.9344 25.4% 100 1.0493 0.72 0.00 SELECT steady_table +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============== ===== ====== ===== ============== +# 1 0x32B0659E6D13E5A2 308.4675 74.6% 100 3.0847 0.48 SELECT unsteady_table +# 2 0x2F621C2B0611518C 104.9344 25.4% 100 1.0493 0.00 SELECT steady_table diff --git a/t/pt-query-digest/samples/slow053.txt b/t/pt-query-digest/samples/slow053.txt index c97655da..51fec151 100644 --- a/t/pt-query-digest/samples/slow053.txt +++ b/t/pt-query-digest/samples/slow053.txt @@ -1,8 +1,7 @@ # Query 1: 2 QPS, 1.90x concurrency, ID 0xA4EAD36B5CEB1C13 at byte 1044 __ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.01 -# Query_time sparkline: | ^^ | +# Scores: V/M = 0.01 # Time range: 2011-02-08 12:00:09 to 12:00:10 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -32,8 +31,7 @@ SELECT * FROM blah WHERE id IS NOT NULL\G # Query 2: 1.50 QPS, 0.03x concurrency, ID 0xAC0EC652760FEEB3 at byte 913 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.03 -# Query_time sparkline: | ^ _ | +# Scores: V/M = 0.03 # Time range: 2011-02-08 12:00:06 to 12:00:08 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -63,8 +61,7 @@ SELECT * FROM bar WHERE id=12\G # Query 3: 1.25 QPS, 0.00x concurrency, ID 0xBB11C6B7F3BAAB30 at byte 521 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2011-02-08 12:00:01 to 12:00:05 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow054.txt b/t/pt-query-digest/samples/slow054.txt index 777f8908..ed380133 100644 --- a/t/pt-query-digest/samples/slow054.txt +++ b/t/pt-query-digest/samples/slow054.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xBB11C6B7F3BAAB30 at byte 1058 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2011-02-08 12:00:01 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/slow055.txt b/t/pt-query-digest/samples/slow055.txt index c920a1ee..c834e436 100644 --- a/t/pt-query-digest/samples/slow055.txt +++ b/t/pt-query-digest/samples/slow055.txt @@ -5,8 +5,7 @@ # Item 1: 0 QPS, 0x concurrency, ID 0xE9800998ECF8427E at byte 420 _______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.01 -# Query_time sparkline: |^ ^ ^ | +# Scores: V/M = 0.01 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= # Count 100 3 diff --git a/t/pt-query-digest/samples/slow056.txt b/t/pt-query-digest/samples/slow056.txt index 8e6571d3..a265aa1f 100644 --- a/t/pt-query-digest/samples/slow056.txt +++ b/t/pt-query-digest/samples/slow056.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x54E0BB9E70EAA792 at byte 596 ______ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2012-11-23 19:56:06 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -38,8 +37,7 @@ select b = b + 30 from t where user_id=1\G # Query 2: 0 QPS, 0x concurrency, ID 0xE9800998ECF8427E at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2012-11-23 19:56:06 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/tcpdump001.txt b/t/pt-query-digest/samples/tcpdump001.txt index cc5de25d..e1d1de9d 100644 --- a/t/pt-query-digest/samples/tcpdump001.txt +++ b/t/pt-query-digest/samples/tcpdump001.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xA3C9C49321D65C30 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-04-12 09:50:16.805123 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -12,7 +11,6 @@ # Query size 100 32 32 32 32 32 0 32 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Query_time distribution # 1us diff --git a/t/pt-query-digest/samples/tcpdump002_report.txt b/t/pt-query-digest/samples/tcpdump002_report.txt index 111be585..41e0592d 100644 --- a/t/pt-query-digest/samples/tcpdump002_report.txt +++ b/t/pt-query-digest/samples/tcpdump002_report.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x5D51E5F01B88B79E at byte 1470 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-04-12 11:00:13.118191 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -13,7 +12,6 @@ # Warning coun 0 0 0 0 0 0 0 0 # String: # Databases mysql -# Errors none # Hosts 127.0.0.1 # Users msandbox # Query_time distribution @@ -29,8 +27,7 @@ administrator command: Connect\G # Query 2: 0 QPS, 0x concurrency, ID 0xE3A3649C5FAC418D at byte 2449 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-04-12 11:00:13.118643 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -41,7 +38,6 @@ administrator command: Connect\G # Warning coun 0 0 0 0 0 0 0 0 # String: # Databases mysql -# Errors none # Hosts 127.0.0.1 # Users msandbox # Query_time distribution @@ -58,8 +54,7 @@ select @@version_comment limit 1\G # Query 3: 0 QPS, 0x concurrency, ID 0xAE5A83B27932AB98 at byte 3298 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-04-12 11:00:13.119079 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -70,7 +65,6 @@ select @@version_comment limit 1\G # Warning coun 0 0 0 0 0 0 0 0 # String: # Databases mysql -# Errors none # Hosts 127.0.0.1 # Users msandbox # Query_time distribution @@ -87,8 +81,7 @@ select "paris in the the spring" as trick\G # Query 4: 0 QPS, 0x concurrency, ID 0xAA353644DE4C4CB4 at byte 4186 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-04-12 11:00:13.119487 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -99,7 +92,6 @@ select "paris in the the spring" as trick\G # Warning coun 0 0 0 0 0 0 0 0 # String: # Databases mysql -# Errors none # Hosts 127.0.0.1 # Users msandbox # Query_time distribution diff --git a/t/pt-query-digest/samples/tcpdump003.txt b/t/pt-query-digest/samples/tcpdump003.txt index d404e3b6..2ae2d210 100644 --- a/t/pt-query-digest/samples/tcpdump003.txt +++ b/t/pt-query-digest/samples/tcpdump003.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x5D51E5F01B88B79E at byte 1455 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-04-12 12:41:46.357853 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= diff --git a/t/pt-query-digest/samples/tcpdump012.txt b/t/pt-query-digest/samples/tcpdump012.txt index cc5de25d..e1d1de9d 100644 --- a/t/pt-query-digest/samples/tcpdump012.txt +++ b/t/pt-query-digest/samples/tcpdump012.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xA3C9C49321D65C30 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-04-12 09:50:16.805123 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -12,7 +11,6 @@ # Query size 100 32 32 32 32 32 0 32 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Query_time distribution # 1us diff --git a/t/pt-query-digest/samples/tcpdump017_report.txt b/t/pt-query-digest/samples/tcpdump017_report.txt index 904558df..1b89de67 100644 --- a/t/pt-query-digest/samples/tcpdump017_report.txt +++ b/t/pt-query-digest/samples/tcpdump017_report.txt @@ -10,8 +10,7 @@ # Query 1: 2.13 QPS, 0.36x concurrency, ID 0xE3A3649C5FAC418D at byte 2548 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.19 -# Query_time sparkline: | ^ ^ | +# Scores: V/M = 0.19 # Time range: 2009-04-12 11:00:13.118643 to 11:00:14.999999 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -21,7 +20,6 @@ # Query size 100 128 32 32 32 32 0 32 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Query_time distribution # 1us @@ -36,6 +34,6 @@ select @@version_comment limit 1\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ====== -# 1 0xE3A3649C5FAC418D 0.6696 100.0% 4 0.1674 1.00 0.19 SELECT +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ====== +# 1 0xE3A3649C5FAC418D 0.6696 100.0% 4 0.1674 0.19 SELECT diff --git a/t/pt-query-digest/samples/tcpdump021.txt b/t/pt-query-digest/samples/tcpdump021.txt index 7f5dbb6d..76ff73c0 100644 --- a/t/pt-query-digest/samples/tcpdump021.txt +++ b/t/pt-query-digest/samples/tcpdump021.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAA8E9FA785927259 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 09:23:49.637394 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -12,7 +11,6 @@ # Query size 35 35 35 35 35 35 0 35 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution @@ -34,8 +32,7 @@ SELECT i FROM d.t WHERE i=?\G # Query 2: 0 QPS, 0x concurrency, ID 0x3F79759E7FA2F117 at byte 1106 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 09:23:49.637892 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -47,7 +44,6 @@ SELECT i FROM d.t WHERE i=?\G # Boolean: # No index use 100% yes, 0% no # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution @@ -69,8 +65,7 @@ SELECT i FROM d.t WHERE i="3"\G # Query 3: 0 QPS, 0x concurrency, ID 0xAA353644DE4C4CB4 at byte 1850 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 09:23:49.638381 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -80,7 +75,6 @@ SELECT i FROM d.t WHERE i="3"\G # Query size 27 27 27 27 27 27 0 27 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Query_time distribution # 1us diff --git a/t/pt-query-digest/samples/tcpdump022.txt b/t/pt-query-digest/samples/tcpdump022.txt index 04fe6b9e..f613e27d 100644 --- a/t/pt-query-digest/samples/tcpdump022.txt +++ b/t/pt-query-digest/samples/tcpdump022.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xC30A1A850F4E510F at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 13:41:12.811188 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -12,7 +11,6 @@ # Query size 47 46 46 46 46 46 0 46 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution @@ -34,8 +32,7 @@ SELECT i,j FROM d.t2 WHERE i=? AND j=?\G # Query 2: 0 QPS, 0x concurrency, ID 0x26EEAE2EADD904A1 at byte 1330 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 13:41:12.811591 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -45,7 +42,6 @@ SELECT i,j FROM d.t2 WHERE i=? AND j=?\G # Query size 52 51 51 51 51 51 0 51 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution diff --git a/t/pt-query-digest/samples/tcpdump023.txt b/t/pt-query-digest/samples/tcpdump023.txt index 34b31182..e240149b 100644 --- a/t/pt-query-digest/samples/tcpdump023.txt +++ b/t/pt-query-digest/samples/tcpdump023.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x8E77A2947B4BC375 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 14:14:55.951863 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -12,7 +11,6 @@ # Query size 42 50 50 50 50 50 0 50 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution @@ -34,8 +32,7 @@ SELECT * FROM d.t3 WHERE v=? OR c=? OR f=?\G # Query 2: 0 QPS, 0x concurrency, ID 0xA0B1C345E8654C18 at byte 1540 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 14:14:55.952344 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -45,7 +42,6 @@ SELECT * FROM d.t3 WHERE v=? OR c=? OR f=?\G # Query size 57 69 69 69 69 69 0 69 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution diff --git a/t/pt-query-digest/samples/tcpdump024.txt b/t/pt-query-digest/samples/tcpdump024.txt index 68a53f11..7002ff30 100644 --- a/t/pt-query-digest/samples/tcpdump024.txt +++ b/t/pt-query-digest/samples/tcpdump024.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x8E77A2947B4BC375 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 14:33:13.711351 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -12,7 +11,6 @@ # Query size 45 50 50 50 50 50 0 50 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution @@ -34,8 +32,7 @@ SELECT * FROM d.t3 WHERE v=? OR c=? OR f=?\G # Query 2: 0 QPS, 0x concurrency, ID 0xA0B1C345E8654C18 at byte 1540 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 14:33:13.711642 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -45,7 +42,6 @@ SELECT * FROM d.t3 WHERE v=? OR c=? OR f=?\G # Query size 54 59 59 59 59 59 0 59 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution diff --git a/t/pt-query-digest/samples/tcpdump025.txt b/t/pt-query-digest/samples/tcpdump025.txt index 462c7908..99b12e3c 100644 --- a/t/pt-query-digest/samples/tcpdump025.txt +++ b/t/pt-query-digest/samples/tcpdump025.txt @@ -1,8 +1,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0x72B6E5BC2632931C at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 14:44:52.709181 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -12,7 +11,6 @@ # Query size 50 42 42 42 42 42 0 42 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution @@ -34,8 +32,7 @@ SELECT * FROM d.t WHERE 1 LIMIT 1;\G # Query 2: 0 QPS, 0x concurrency, ID 0xDDF5E71E9A66B752 at byte 1014 _____ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 14:44:52.709597 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -47,7 +44,6 @@ SELECT * FROM d.t WHERE 1 LIMIT 1;\G # Boolean: # No index use 100% yes, 0% no # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution diff --git a/t/pt-query-digest/samples/tcpdump033.txt b/t/pt-query-digest/samples/tcpdump033.txt index 08a06069..e392dfb1 100644 --- a/t/pt-query-digest/samples/tcpdump033.txt +++ b/t/pt-query-digest/samples/tcpdump033.txt @@ -12,8 +12,7 @@ # Query 1: 2.03k QPS, 0.28x concurrency, ID 0x6EE88728F6F29C72 at byte 800 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-12-18 08:44:07.235011 to 08:44:07.238467 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -25,7 +24,6 @@ # Boolean: # No index use 100% yes, 0% no # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 (3/42%), 3 (2/28%), 4 (1/14%), 5 (1/14%) # Query_time distribution @@ -47,8 +45,7 @@ select * from d.t where name="adam"\G # Query 2: 1.17k QPS, 0.19x concurrency, ID 0xECBCD0412B5E497A at byte 9215 # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: 2009-12-18 08:44:07.234727 to 08:44:07.238999 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -58,7 +55,6 @@ select * from d.t where name="adam"\G # Query size 37 217 42 45 43.40 44.60 1.31 42.48 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 (1/20%), 3 (1/20%), 4 (1/20%), 5 (1/20%)... 1 more # Query_time distribution @@ -80,8 +76,7 @@ select * from d.t where name="daniel"\G # Query 3: 1.70k QPS, 0x concurrency, ID 0x559914DA8A7B7F28 at byte 8202 _ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | | +# Scores: V/M = 0.00 # Time range: 2009-12-18 08:44:07.236509 to 08:44:07.238274 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -91,7 +86,6 @@ select * from d.t where name="daniel"\G # Query size 10 60 20 20 20 20 0 20 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Query_time distribution # 1us @@ -105,11 +99,11 @@ select * from d.t where name="daniel"\G DEALLOCATE PREPARE 4\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0x6EE88728F6F29C72 0.0010 54.4% 7 0.0001 1.00 0.00 SELECT d.t -# 2 0xECBCD0412B5E497A 0.0008 45.6% 5 0.0002 1.00 0.00 SELECT d.t -# 3 0x559914DA8A7B7F28 0.0000 0.0% 3 0.0000 1.00 0.00 +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0x6EE88728F6F29C72 0.0010 54.4% 7 0.0001 0.00 SELECT d.t +# 2 0xECBCD0412B5E497A 0.0008 45.6% 5 0.0002 0.00 SELECT d.t +# 3 0x559914DA8A7B7F28 0.0000 0.0% 3 0.0000 0.00 # Prepared statements # Rank Query ID PREP PREP Response EXEC EXEC Response Item diff --git a/t/pt-query-digest/samples/tcpdump041.txt b/t/pt-query-digest/samples/tcpdump041.txt index 09edac73..62961eff 100644 --- a/t/pt-query-digest/samples/tcpdump041.txt +++ b/t/pt-query-digest/samples/tcpdump041.txt @@ -10,8 +10,7 @@ # Query 1: 0 QPS, 0x concurrency, ID 0xAA8E9FA785927259 at byte 0 ________ # This item is included in the report because it matches --limit. -# Scores: Apdex = 1.00 [1.0]*, V/M = 0.00 -# Query_time sparkline: | ^ | +# Scores: V/M = 0.00 # Time range: all events occurred at 2009-12-08 09:23:49.637394 # Attribute pct total min max avg 95% stddev median # ============ === ======= ======= ======= ======= ======= ======= ======= @@ -21,7 +20,6 @@ # Query size 100 35 35 35 35 35 0 35 # Warning coun 0 0 0 0 0 0 0 0 # String: -# Errors none # Hosts 127.0.0.1 # Statement id 2 # Query_time distribution @@ -42,9 +40,9 @@ PREPARE SELECT i FROM d.t WHERE i=?\G SELECT i FROM d.t WHERE i=?\G # Profile -# Rank Query ID Response time Calls R/Call Apdx V/M Item -# ==== ================== ============= ===== ====== ==== ===== ========== -# 1 0xAA8E9FA785927259 0.0003 100.0% 1 0.0003 1.00 0.00 SELECT d.t +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ========== +# 1 0xAA8E9FA785927259 0.0003 100.0% 1 0.0003 0.00 SELECT d.t # Prepared statements # Rank Query ID PREP PREP Response EXEC EXEC Response Item diff --git a/t/pt-query-digest/samples/tcpdump043_report.txt b/t/pt-query-digest/samples/tcpdump043_report.txt new file mode 100644 index 00000000..668eb4a5 --- /dev/null +++ b/t/pt-query-digest/samples/tcpdump043_report.txt @@ -0,0 +1,40 @@ + +# Overall: 1 total, 1 unique, 0 QPS, 0x concurrency ______________________ +# Time range: all events occurred at 2013-01-24 13:03:28.672987 +# Attribute total min max avg 95% stddev median +# ============ ======= ======= ======= ======= ======= ======= ======= +# Exec time 4s 4s 4s 4s 4s 0 4s +# Rows affecte 0 0 0 0 0 0 0 +# Query size 30 30 30 30 30 0 30 +# Warning coun 0 0 0 0 0 0 0 + +# Query 1: 0 QPS, 0x concurrency, ID 0x5D51E5F01B88B79E at byte 0 ________ +# This item is included in the report because it matches --limit. +# Scores: V/M = 0.00 +# Time range: all events occurred at 2013-01-24 13:03:28.672987 +# Attribute pct total min max avg 95% stddev median +# ============ === ======= ======= ======= ======= ======= ======= ======= +# Count 100 1 +# Exec time 100 4s 4s 4s 4s 4s 0 4s +# Rows affecte 0 0 0 0 0 0 0 0 +# Query size 100 30 30 30 30 30 0 30 +# Warning coun 0 0 0 0 0 0 0 0 +# String: +# Error msg Got packets out of order +# Errors 1156 +# Hosts 127.0.0.1 +# Query_time distribution +# 1us +# 10us +# 100us +# 1ms +# 10ms +# 100ms +# 1s ################################################################ +# 10s+ +administrator command: Connect\G + +# Profile +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ============= +# 1 0x5D51E5F01B88B79E 3.5363 100.0% 1 3.5363 0.00 ADMIN CONNECT diff --git a/t/pt-query-digest/samples/tcpdump044_report.txt b/t/pt-query-digest/samples/tcpdump044_report.txt new file mode 100644 index 00000000..4d3f14b2 --- /dev/null +++ b/t/pt-query-digest/samples/tcpdump044_report.txt @@ -0,0 +1,39 @@ + +# Overall: 1 total, 1 unique, 0 QPS, 0x concurrency ______________________ +# Time range: all events occurred at 2013-01-22 09:55:57.793375 +# Attribute total min max avg 95% stddev median +# ============ ======= ======= ======= ======= ======= ======= ======= +# Exec time 4s 4s 4s 4s 4s 0 4s +# Rows affecte 0 0 0 0 0 0 0 +# Query size 30 30 30 30 30 0 30 +# Warning coun 0 0 0 0 0 0 0 + +# Query 1: 0 QPS, 0x concurrency, ID 0x5D51E5F01B88B79E at byte 0 ________ +# This item is included in the report because it matches --limit. +# Scores: V/M = 0.00 +# Time range: all events occurred at 2013-01-22 09:55:57.793375 +# Attribute pct total min max avg 95% stddev median +# ============ === ======= ======= ======= ======= ======= ======= ======= +# Count 100 1 +# Exec time 100 4s 4s 4s 4s 4s 0 4s +# Rows affecte 0 0 0 0 0 0 0 0 +# Query size 100 30 30 30 30 30 0 30 +# Warning coun 0 0 0 0 0 0 0 0 +# String: +# Error msg Client closed connection during handshake +# Hosts 100.0.0.2 +# Query_time distribution +# 1us +# 10us +# 100us +# 1ms +# 10ms +# 100ms +# 1s ################################################################ +# 10s+ +administrator command: Connect\G + +# Profile +# Rank Query ID Response time Calls R/Call V/M Item +# ==== ================== ============= ===== ====== ===== ============= +# 1 0x5D51E5F01B88B79E 3.8195 100.0% 1 3.8195 0.00 ADMIN CONNECT diff --git a/t/pt-query-digest/slowlog_analyses.t b/t/pt-query-digest/slowlog_analyses.t index 978d3994..eb4eef0f 100644 --- a/t/pt-query-digest/slowlog_analyses.t +++ b/t/pt-query-digest/slowlog_analyses.t @@ -276,24 +276,6 @@ ok( 'Distill UNLOCK and LOCK TABLES' ); -# Test --table-access. -ok( - no_diff( - sub { pt_query_digest::main(@args, $sample.'slow020.txt', qw(--no-report --table-access)) }, - "t/pt-query-digest/samples/slow020_table_access.txt", - ), - 'Analysis for slow020 with --table-access' -); - -# This one tests that the list of tables is unique. -ok( - no_diff( - sub { pt_query_digest::main(@args, $sample.'slow030.txt', qw(--no-report --table-access)) }, - "t/pt-query-digest/samples/slow030_table_access.txt" - ), - 'Analysis for slow030 with --table-access' -); - ok( no_diff( sub { pt_query_digest::main(@args, $sample.'slow034.txt', qw(--order-by Lock_time:sum), @@ -391,7 +373,6 @@ ok( # ############################################################################# # Issue 1124: Make mk-query-digest profile include variance-to-mean ratio -# Issue 1054: Add Apdex scores to mk-query-digest report # ############################################################################# ok( no_diff( @@ -401,14 +382,6 @@ ok( 'Analysis for slow052 (Apdex and V/M)', ); -ok( - no_diff( - sub { pt_query_digest::main(@args, qw(--apdex-t 0.1), '--report-format', 'query_report,profile', $sample.'slow052.txt') }, - "t/pt-query-digest/samples/slow052-apdex-t-0.1.txt", - ), - 'Analysis for slow052 (Apdex T = 0.1)', -); - # ############################################################################# # Bug 821694: pt-query-digest doesn't recognize hex InnoDB txn IDs # ############################################################################# diff --git a/t/pt-query-digest/statistics.t b/t/pt-query-digest/statistics.t deleted file mode 100644 index 6609f592..00000000 --- a/t/pt-query-digest/statistics.t +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env perl - -BEGIN { - die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" - unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; - unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; -}; - -use strict; -use warnings FATAL => 'all'; -use English qw(-no_match_vars); -use Test::More tests => 1; - -use PerconaTest; - -require "$trunk/bin/pt-query-digest"; - -my @args = qw(--no-report --statistics); -my $sample = "$trunk/t/lib/samples/slowlogs/"; - -ok( - no_diff( - sub { pt_query_digest::main(@args, $sample.'slow002.txt') }, - "t/pt-query-digest/samples/stats-slow002.txt" - ), - '--statistics for slow002.txt', -); - -# ############################################################################# -# Done. -# ############################################################################# -exit; diff --git a/t/pt-stalk/option_sanity.t b/t/pt-stalk/option_sanity.t new file mode 100644 index 00000000..66077735 --- /dev/null +++ b/t/pt-stalk/option_sanity.t @@ -0,0 +1,24 @@ +#!/usr/bin/env perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +use PerconaTest; + +my $output = `$trunk/bin/pt-stalk --help`; + +like( + $output, + qr/^\s+--verbose\s+2/m, + "Default --verbose=2" +); + +done_testing; diff --git a/t/pt-stalk/pt-stalk.t b/t/pt-stalk/pt-stalk.t index 30048726..464a4d45 100644 --- a/t/pt-stalk/pt-stalk.t +++ b/t/pt-stalk/pt-stalk.t @@ -28,11 +28,28 @@ my $cnf = "/tmp/12345/my.sandbox.cnf"; my $pid_file = "/tmp/pt-stalk.pid.$PID"; my $log_file = "/tmp/pt-stalk.log.$PID"; my $dest = "/tmp/pt-stalk.collect.$PID"; +my $int_file = "/tmp/pt-stalk-after-interval-sleep"; my $pid; -diag(`rm $pid_file 2>/dev/null`); -diag(`rm $log_file 2>/dev/null`); -diag(`rm -rf $dest 2>/dev/null`); +sub cleanup { + diag(`rm $pid_file $log_file $int_file 2>/dev/null`); + diag(`rm -rf $dest 2>/dev/null`); +} + +sub wait_n_cycles { + my ($n) = @_; + PerconaTest::wait_until( + sub { + return 0 unless -f "$dest/after_interval_sleep"; + my $n_cycles = `wc -l "$dest/after_interval_sleep" | awk '{print \$1}'`; + $n_cycles ||= ''; + chomp($n_cycles); + return ($n_cycles || 0) >= $n; + }, + 1.5, + 15 + ); +} # ########################################################################### # Test that it won't run if can't connect to MySQL. @@ -56,11 +73,14 @@ is( # ########################################################################### # Test that it runs and dies normally. # ########################################################################### -diag(`rm $pid_file 2>/dev/null`); -diag(`rm $log_file 2>/dev/null`); -diag(`rm -rf $dest 2>/dev/null`); -$retval = system("$trunk/bin/pt-stalk --daemonize --pid $pid_file --log $log_file --dest $dest -- --defaults-file=$cnf"); +cleanup(); + +# As of v2.1.9 when --verbose was added, non-matching checks are not +# printed by default. So we use the --plugin to tell us when the tool +# has completed a cycle. + +$retval = system("$trunk/bin/pt-stalk --daemonize --pid $pid_file --log $log_file --dest $dest --plugin $trunk/t/pt-stalk/samples/plugin002.sh -- --defaults-file=$cnf"); is( $retval >> 8, @@ -94,21 +114,16 @@ is( "pt-stalk is running" ); -PerconaTest::wait_for_sh("grep -q 'Check results' $log_file >/dev/null"); +wait_n_cycles(2); +PerconaTest::kill_program(pid_file => $pid_file); + $output = `cat $log_file 2>/dev/null`; -like( +unlike( $output, qr/Check results: Threads_running=\d+, matched=no, cycles_true=0/, - "Check results logged" + "Non-matching results not logged because --verbose=2" ) or diag(`cat $log_file 2>/dev/null`, `cat $dest/*-output 2>/dev/null`); -$retval = system("kill $pid 2>/dev/null"); -is( - $retval >> 0, - 0, - "Killed pt-stalk" -); - PerconaTest::wait_until(sub { !-f $pid_file }); ok( @@ -123,12 +138,56 @@ like( "Caught signal logged" ) or diag(`cat $log_file 2>/dev/null`, `cat $dest/*-output 2>/dev/null`); +# ############################################################################# +# --verbose 3 (non-matching results) +# ############################################################################# + +cleanup(); + +$retval = system("$trunk/bin/pt-stalk --daemonize --pid $pid_file --log $log_file --dest $dest --verbose 3 -- --defaults-file=$cnf"); + +PerconaTest::wait_for_files($pid_file, $log_file); +PerconaTest::wait_for_sh("grep -q 'Check results' $log_file >/dev/null"); +PerconaTest::kill_program(pid_file => $pid_file); + +$output = `cat $log_file 2>/dev/null`; +like( + $output, + qr/Check results: Threads_running=\d+, matched=no, cycles_true=0/, + "Matching results logged with --verbose 3" +) or diag(`cat $log_file 2>/dev/null`, `cat $dest/*-output 2>/dev/null`); + +# ############################################################################# +# --verbose 1 (just errors and warnings) +# ############################################################################# + +cleanup(); + +$retval = system("$trunk/bin/pt-stalk --daemonize --pid $pid_file --log $log_file --dest $dest --verbose 1 --plugin $trunk/t/pt-stalk/samples/plugin002.sh -- --defaults-file=$cnf"); + +PerconaTest::wait_for_files($pid_file, $log_file); +wait_n_cycles(2); +PerconaTest::kill_program(pid_file => $pid_file); + +$output = `cat $log_file 2>/dev/null`; + +like( + $output, + qr/Caught signal, exiting/, + "Warning logged (--verbose 1)" +); + +unlike( + $output, + qr/Start|Collect|Check/i, + "No run info log (--verbose 1)" +); + # ########################################################################### # Test collect. # ########################################################################### -diag(`rm $pid_file 2>/dev/null`); -diag(`rm $log_file 2>/dev/null`); -diag(`rm $dest/* 2>/dev/null`); + +cleanup(); # We'll have to watch Uptime since it's the only status var that's going # to be predictable. @@ -180,10 +239,10 @@ like( "Trigger file logs how pt-stalk was ran" ); -chomp($output = `cat $log_file 2>/dev/null | grep 'Collector PID'`); +chomp($output = `cat $log_file 2>/dev/null | grep 'Collect [0-9] PID'`); like( $output, - qr/Collector PID \d+/, + qr/Collect 1 PID \d+/, "Collector PID logged" ) or diag( @@ -195,9 +254,8 @@ or diag( # ########################################################################### # Triggered but --no-collect. # ########################################################################### -diag(`rm $pid_file 2>/dev/null`); -diag(`rm $log_file 2>/dev/null`); -diag(`rm $dest/* 2>/dev/null`); + +cleanup(); (undef, $uptime) = $dbh->selectrow_array("SHOW STATUS LIKE 'Uptime'"); $threshold = $uptime + 2; @@ -209,7 +267,7 @@ PerconaTest::wait_until(sub { !-f $pid_file }); $output = `cat $log_file 2>/dev/null`; like( $output, - qr/Collect triggered/, + qr/Collect 1 triggered/, "Collect triggered" ); @@ -227,6 +285,8 @@ ok( # --config # ############################################################################# +cleanup(); + diag(`cp $ENV{HOME}/.pt-stalk.conf $ENV{HOME}/.pt-stalk.conf.original 2>/dev/null`); diag(`cp $trunk/t/pt-stalk/samples/config001.conf $ENV{HOME}/.pt-stalk.conf`); @@ -254,9 +314,8 @@ diag(`cp $ENV{HOME}/.pt-stalk.conf.original $ENV{HOME}/.pt-stalk.conf 2>/dev/nul # ############################################################################# # Don't stalk, just collect. # ############################################################################# -diag(`rm $pid_file 2>/dev/null`); -diag(`rm $log_file 2>/dev/null`); -diag(`rm $dest/* 2>/dev/null`); + +cleanup(); $retval = system("$trunk/bin/pt-stalk --no-stalk --run-time 2 --dest $dest --prefix nostalk --pid $pid_file -- --defaults-file=$cnf >$log_file 2>&1"); @@ -343,9 +402,7 @@ unlike( # ############################################################################# # Done. # ############################################################################# -diag(`rm $pid_file 2>/dev/null`); -diag(`rm $log_file 2>/dev/null`); +cleanup(); diag(`rm -rf $dest 2>/dev/null`); ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); - done_testing; diff --git a/t/pt-stalk/samples/plugin002.sh b/t/pt-stalk/samples/plugin002.sh new file mode 100644 index 00000000..65093aa1 --- /dev/null +++ b/t/pt-stalk/samples/plugin002.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +after_interval_sleep() { + date >> "$OPT_DEST/after_interval_sleep" +} diff --git a/t/pt-table-checksum/bugs.t b/t/pt-table-checksum/bugs.t index 4f2c9969..0cc78dde 100644 --- a/t/pt-table-checksum/bugs.t +++ b/t/pt-table-checksum/bugs.t @@ -256,7 +256,7 @@ SKIP: { $output = output( sub { pt_table_checksum::main(@args) }, stderr => 1 ); - my $re = qr/ has binlog_format .*? has binlog_format (\S+)\./msi; + my $re = qr/Replica .+? has binlog_format (\S+)/msi; like( $output, $re, diff --git a/t/pt-table-sync/diff_where.t b/t/pt-table-sync/diff_where.t index dce9c625..e1ba8b60 100644 --- a/t/pt-table-sync/diff_where.t +++ b/t/pt-table-sync/diff_where.t @@ -9,7 +9,7 @@ BEGIN { use strict; use warnings FATAL => 'all'; use English qw(-no_match_vars); -use Test::More tests => 1; +use Test::More; use PerconaTest; use Sandbox; @@ -57,7 +57,28 @@ test_diff_where( where => "((`id` >= '7')) AND ((`id` <= '9'))", ); +test_diff_where( + name => "Lower oob chunk (bug 918056)", + file => "$sample/bug-918056-ddl.sql", + diff => { + chunk => '3', + chunk_index => 'PRIMARY', + cnt_diff => '49', + crc_diff => '0', + db => 'test', + lower_boundary => undef, + master_cnt => '0', + master_crc => '0', + table => 'test.history', + tbl => 'history', + this_cnt => '49', + this_crc => '0', + upper_boundary => '21,21,1045' + }, + where => "((`uid` < '21') OR (`uid` = '21' AND `nid` <= '1045'))", +); + # ############################################################################# # Done. # ############################################################################# -exit; +done_testing; diff --git a/t/pt-table-sync/replicate.t b/t/pt-table-sync/replicate.t new file mode 100644 index 00000000..b9fc075c --- /dev/null +++ b/t/pt-table-sync/replicate.t @@ -0,0 +1,90 @@ +#!/usr/bin/env perl + +BEGIN { + die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n" + unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH}; + unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib"; + + # Don't add /* trace */ messages to --print queries becuase they + # contain non-determinstic info like user, etc. + $ENV{PT_TEST_NO_TRACE} = 1; +}; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +use PerconaTest; +use Sandbox; +require "$trunk/bin/pt-table-sync"; + +my $dp = new DSNParser(opts=>$dsn_opts); +my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp); +my $master_dbh = $sb->get_dbh_for('master'); +my $slave1_dbh = $sb->get_dbh_for('slave1'); + +if ( !$master_dbh ) { + plan skip_all => 'Cannot connect to sandbox master'; +} +elsif ( !$slave1_dbh ) { + plan skip_all => 'Cannot connect to sandbox slave1'; +} + +my $master_dsn = $sb->dsn_for('master'); +my $slave1_dsn = $sb->dsn_for('slave1'); + +my $output; +my $sample = "t/pt-table-sync/samples"; + +# ############################################################################# +# --replicate tests +# ############################################################################# + +# ############################################################################# +# Bug 918056: pt-table-sync false-positive error "Cannot nibble table because +# MySQL chose no index instead of the PRIMARY index" +# https://bugs.launchpad.net/percona-toolkit/+bug/918056 +# ############################################################################# + +# The slave has 49 extra rows on the low end, e.g. master has rows 50+ +# but slave has rows 1-49 and 50+. This tests syncing the lower oob chunk. +$sb->create_dbs($master_dbh, [qw(bug918056)]); +$sb->load_file('master', "$sample/bug-918056-master.sql", "bug918056"); +$sb->load_file('slave1', "$sample/bug-918056-slave.sql", "bug918056"); + +ok( + no_diff( + sub { + pt_table_sync::main($master_dsn, qw(--replicate percona.checksums), + qw(--print)) + }, + "$sample/bug-918056-print.txt", + stderr => 1, + ), + "Sync lower oob (bug 918056)" +); + +# Test syncing the upper oob chunk. +$sb->load_file('master', "$sample/upper-oob-master.sql"); +$sb->load_file('slave1', "$sample/upper-oob-slave.sql"); + +ok( + no_diff( + sub { + pt_table_sync::main($master_dsn, qw(--replicate percona.checksums), + qw(--print)) + }, + "$sample/upper-oob-print.txt", + stderr => 1, + ), + "Sync upper oob (bug 918056)" +); + +# ############################################################################# +# Done. +# ############################################################################# +$sb->wipe_clean($master_dbh); +$sb->wipe_clean($slave1_dbh); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +done_testing; diff --git a/t/pt-table-sync/samples/bug-918056-ddl.sql b/t/pt-table-sync/samples/bug-918056-ddl.sql new file mode 100644 index 00000000..cac96297 --- /dev/null +++ b/t/pt-table-sync/samples/bug-918056-ddl.sql @@ -0,0 +1,6 @@ +CREATE TABLE `history` ( + `uid` int(11) NOT NULL DEFAULT '0', + `nid` int(11) NOT NULL DEFAULT '0', + `timestamp` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`uid`,`nid`) +) ENGINE=InnoDB; diff --git a/t/pt-table-sync/samples/bug-918056-master.sql b/t/pt-table-sync/samples/bug-918056-master.sql new file mode 100644 index 00000000..f67a0ea5 --- /dev/null +++ b/t/pt-table-sync/samples/bug-918056-master.sql @@ -0,0 +1,59 @@ +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +DROP TABLE IF EXISTS `history`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `history` ( + `uid` int(11) NOT NULL DEFAULT '0', + `nid` int(11) NOT NULL DEFAULT '0', + `timestamp` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`uid`,`nid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +LOCK TABLES `history` WRITE; +/*!40000 ALTER TABLE `history` DISABLE KEYS */; +INSERT INTO `history` VALUES (21,1045,1356390977),(21,15077,1355862530),(21,15091,1356389282),(21,15093,1356790060),(25,1045,1357937579),(25,1046,1357662059),(54,14842,1356709584),(54,15068,1355337180),(54,15070,1355431148),(54,15075,1355771791),(54,15080,1355936015),(54,15087,1356920353),(54,15089,1356368911),(54,15090,1356920381),(54,15091,1356537468),(54,15092,1356626267),(54,15093,1356979080),(54,15095,1357323810),(54,15097,1357310198),(54,15098,1357323824),(54,15107,1357853282),(54,15108,1357822348),(54,15110,1357851189),(59,1045,1357066507),(59,1227,1355840257),(62,1045,1357949159),(62,1046,1357663553),(62,4565,1355352089),(65,1045,1357764409),(67,1045,1357930070),(67,1046,1355750176),(67,1266,1355495161),(74,1046,1357662795),(105,1045,1357254374),(105,1046,1357254296),(106,1045,1355763248),(120,1045,1356798982),(120,1227,1356798980),(128,1046,1355498580),(143,1046,1357337808),(149,1045,1357238805),(159,1045,1357752547),(159,1046,1357665158),(174,1045,1357679824),(174,1046,1357679071),(174,15108,1357766878),(175,15097,1357325775),(187,1045,1357324089),(187,1046,1357324096),(243,14,1356393835),(243,1045,1356683074),(244,1046,1355727280),(251,1046,1357337118),(256,1045,1358088842),(259,1045,1357075192),(259,1046,1356007577),(264,1045,1357327207),(264,1227,1357327205),(264,1236,1357327180),(288,1046,1356443078),(289,1045,1357913495),(292,1046,1355414251),(297,1045,1357749582),(300,1045,1357335518),(305,1046,1357336628),(308,1085,1355358490),(309,1045,1357258403),(309,1085,1355272403),(317,1045,1357351288),(325,1045,1357764751),(325,1046,1357337560),(325,1236,1357224022),(359,1045,1357932214),(374,1045,1357952255),(399,1045,1357340847),(399,1046,1357340845),(413,1046,1356389902),(424,1045,1355266998),(424,1046,1357339972),(424,11496,1355245935),(424,11945,1356985024),(424,11950,1357584209),(424,15105,1357680908),(434,1236,1355508145),(437,1045,1357964301),(454,1046,1357333076),(454,1236,1357675386),(467,1045,1357844178),(467,1046,1357058973),(467,1085,1355254593),(470,1045,1358025068),(538,1045,1357323914),(594,1085,1355239973),(594,1236,1357249373),(608,1045,1355835306),(620,1085,1355235210),(629,1045,1355776916),(659,1045,1357962784),(692,1045,1357933867),(731,1045,1357355342),(737,1045,1357751581),(795,1045,1355783770),(795,1046,1357329859),(812,1045,1358050502),(822,1045,1357324207),(822,1227,1357324204),(835,1045,1357912747),(837,1045,1357768710),(841,1040,1357337094),(841,1045,1357337094),(841,1046,1357337063),(884,1045,1357932955),(896,1045,1358023011),(899,1045,1357942562),(914,1045,1358124965),(925,1045,1358008745),(930,1236,1355830584),(946,1045,1357908733),(964,1045,1357828765),(967,1045,1357328027),(970,1045,1357520222),(974,1045,1357520392),(979,1045,1358100819),(981,1046,1357337252),(994,1045,1357329322),(1014,1046,1357338393),(1018,1045,1357838644),(1018,1046,1357325164),(1038,1045,1355810285),(1068,1045,1358004694),(1089,1045,1357949393),(1091,1045,1358093921),(1093,1046,1357250453),(1100,1045,1357737248),(1107,1046,1357338122),(1136,1045,1358103728),(1136,1227,1357921864),(1138,1046,1357338689),(1139,1045,1357354016),(1176,1045,1358119296),(1176,1227,1357988525),(1191,1236,1357942843),(1197,1045,1357080039),(1197,1046,1357338168),(1197,1227,1357080039),(1197,1236,1357080032),(1198,1046,1357340172),(1201,1085,1355244720),(1206,1046,1356431705),(1210,1045,1358084588),(1221,1085,1355241319),(1256,1046,1358163447),(1321,1045,1357327914),(1337,1046,1355689409),(1340,1045,1358099346),(1340,1236,1357512667),(1343,1045,1357927779),(1354,1045,1357663844),(1401,1046,1357339965),(1405,1045,1358055553),(1405,1046,1357935118),(1410,1045,1357329332),(1410,15106,1357769075),(1467,1045,1357960693),(1499,1045,1357074014),(1510,1085,1355256156),(1520,1045,1357645128),(1520,1227,1357641928),(1520,1236,1357644899),(1604,1045,1357749613),(1626,1045,1356985157),(1640,1045,1357234823),(1643,1046,1357337085),(1648,1045,1357671787),(1658,1236,1355872488),(1666,1045,1357682842),(1668,1045,1357933107),(1668,1085,1355243910),(1784,1045,1357960104),(1784,1236,1357785209),(1820,1045,1357598059),(1827,1045,1357937023),(1847,1085,1355337249),(1891,1046,1357341042),(1905,1045,1357391081),(1905,1085,1355244740),(1909,1045,1358111972),(1909,1046,1357855319),(1909,1227,1355628676),(1915,1045,1357231460),(1933,1046,1357336423),(1967,1045,1357605511),(1972,1046,1357241548),(1976,1045,1357968515),(1978,1045,1357619518),(1980,1046,1358076861),(1981,1236,1356111049),(2015,1045,1357281779),(2015,1227,1357281778),(2018,1046,1357326899),(2040,1085,1355246910),(2049,1045,1357687329),(2058,1046,1357340351),(2061,1045,1357944806),(2061,1046,1357340464),(2079,1045,1357352724),(2079,1236,1357352728),(2083,1045,1357584295),(2107,1045,1357773329),(2143,1045,1357623158),(2182,1045,1357964610),(2184,1045,1357085530),(2184,1227,1357085499),(2193,1045,1357965765),(2198,1045,1357268337),(2223,1045,1358132951),(2223,1227,1357278095),(2259,1046,1356643652),(2262,1046,1356269860),(2271,1045,1358095419),(2279,1045,1355938722),(2286,1046,1355469256),(2289,1085,1355237184),(2312,1045,1357264420),(2317,1085,1355275914),(2318,1046,1356612100),(2328,1045,1357327811),(2330,1085,1355323629),(2350,1045,1358007629),(2370,1236,1357420725),(2397,1045,1357353835),(2411,1045,1357609059),(2423,1045,1357933913),(2427,1046,1357339432),(2455,1045,1357548003),(2463,1046,1357276433),(2465,1046,1357338132),(2485,1046,1356904286),(2485,1085,1355334761),(2518,1236,1356707976),(2522,1045,1357793674),(2538,1045,1357267442),(2543,1085,1355254304),(2561,1085,1355248186),(2587,1045,1355787098),(2618,1045,1355629436),(2618,1085,1355241036),(2618,1227,1355629436),(2618,1236,1356049718),(2624,1045,1357353965),(2629,1045,1356726368),(2629,1227,1356726367),(2634,1045,1357575100),(2647,1045,1356690281),(2647,1046,1356777159),(2652,1045,1358124796),(2656,1045,1358125904),(2664,1085,1355316722),(2689,1045,1357922586),(2689,1227,1357922583),(2698,1046,1357332436),(2702,1045,1355581198),(2708,1046,1357132299),(2717,1046,1358082531),(2721,1045,1358092575),(2721,1046,1357341491),(2751,1045,1357631439),(2752,1045,1358148679),(2771,1085,1355241299),(2773,1046,1357338130),(2804,1045,1357088269),(2831,1045,1357260082),(2844,1046,1356441364),(2856,1045,1357526234),(2861,1045,1357954064),(2868,1046,1356717987),(2895,1045,1357779884),(2895,1046,1357779828),(2895,1227,1357779883),(2895,1236,1356547854),(2896,1045,1357328030),(2906,1045,1357348045),(2906,1046,1357964957),(2906,1236,1357399873),(2907,1045,1355855182),(2936,1046,1358016024),(2939,1045,1355512254),(2939,1227,1355512254),(2952,1045,1357685546),(2952,1227,1357685545),(2975,1045,1357682283),(2980,1045,1357335535),(2987,1045,1358011826),(3016,1046,1357337967),(3033,1045,1357646608),(3039,1236,1357667878),(3050,1045,1358005753),(3074,1236,1357500614),(3076,1045,1357933142),(3076,1046,1357328824),(3086,1045,1357948121),(3087,1045,1357930401),(3092,1045,1357261050),(3093,1045,1357932436),(3152,1045,1357933431),(3154,1045,1355781710),(3154,1046,1357340070),(3168,1045,1355577002),(3168,1227,1355577001),(3173,1045,1355865973),(3178,1046,1357336444),(3195,1046,1357249333),(3199,1042,1357336935),(3199,1046,1357336936),(3200,1045,1357353200),(3226,1045,1357087106),(3228,1045,1357676384),(3238,1045,1357347374),(3238,1236,1357849373),(3249,1045,1357943868),(3275,1045,1358141158),(3283,1045,1357347564),(3293,1045,1355508619),(3295,1045,1356040073),(3307,1085,1355263569),(3314,1045,1355809141),(3316,1046,1357336463),(3320,7752,1357947872),(3326,1045,1357778618),(3371,1045,1357282950),(3373,1045,1357477115),(3375,11950,1357420670),(3395,1085,1355175022),(3425,1045,1358129585),(3427,1045,1357952965),(3456,1085,1355369239),(3463,1046,1355726997),(3494,1045,1357937672),(3494,1085,1355266877),(3523,1045,1358007508),(3530,1045,1357307944),(3565,1045,1358105949),(3565,1046,1357003302),(3565,1227,1358105949),(3574,1046,1357338118),(3595,1085,1355282329),(3611,1045,1358088620),(3619,1046,1357337515),(3631,1045,1357617499),(3641,1045,1355840944),(3641,1085,1355316052),(3657,1085,1355248766),(3663,1045,1355175684),(3663,1227,1355175683),(3687,1045,1357248005),(3687,1227,1357248004),(3688,1046,1357664522),(3747,1045,1357622645),(3750,1045,1357080677),(3753,1046,1357340369),(3769,1045,1357040918),(3792,15106,1357865551),(3810,1045,1357619187),(3810,1085,1355257504),(3812,1046,1357335893),(3830,1045,1357753623),(3835,1046,1356786937),(3897,1045,1358099059),(3897,1227,1357420136),(3897,1236,1357420149),(3957,1045,1356204181),(3961,15072,1355507103),(3965,1085,1355262163),(3984,1236,1355874969),(4040,1045,1358045888),(4047,1045,1357353890),(4060,1046,1356437805),(4083,1046,1357337759),(4094,1085,1355235473),(4110,1045,1357142222),(4116,1045,1357950510),(4127,1045,1358099990),(4133,1046,1357178238),(4133,1085,1355334109),(4133,1236,1355440614),(4149,1085,1355279787),(4175,1045,1357946276),(4181,1045,1357696852),(4181,1236,1357701857),(4186,1045,1358020014),(4202,1045,1357549673),(4213,1236,1355810482),(4223,1045,1357970842),(4223,1046,1357880835),(4223,1227,1357970840),(4246,1045,1357667699),(4247,1046,1355747196),(4274,1046,1357906155),(4284,1085,1355235412),(4290,1045,1357224727),(4293,1045,1357938966),(4307,1046,1357256016),(4309,1046,1356087794),(4331,1045,1357359786),(4336,1045,1357619723),(4344,1085,1355238389),(4374,1085,1355244112),(4408,1085,1355257741),(4408,1236,1357935995),(4412,1045,1357933725),(4416,1046,1357244560),(4418,1085,1355372204),(4466,1045,1357926804),(4467,1045,1357926849),(4484,1046,1358159475),(4490,1045,1355510742),(4505,1045,1357291997),(4511,1085,1355275485),(4518,1085,1355242509),(4529,1045,1357948107),(4531,1045,1357326406),(4540,12263,1358112045),(4544,1085,1355252214),(4568,1236,1357086486),(4572,1045,1357534414),(4587,1236,1355178796),(4604,1046,1357323654),(4625,1045,1358008425),(4648,1046,1356641192),(4660,1045,1356125008),(4681,1045,1357939675),(4684,1045,1355251344),(4684,1085,1355251366),(4690,1045,1357931422),(4708,1045,1357933024),(4739,1045,1357769458),(4745,1045,1356147427),(4745,1046,1357738546),(4745,1085,1355293639),(4791,1045,1356122911),(4791,1227,1356122838),(4813,1045,1356367047),(4820,1046,1355477643),(4821,1045,1357694070),(4833,1045,1357980015),(4839,1045,1357998299),(4892,1045,1357665876),(4899,1236,1357747941),(4903,1045,1357353039),(4920,1045,1357225224),(4951,1045,1357011659),(4968,1045,1357758330),(4968,1046,1357243756),(4970,1045,1357936269),(4975,1045,1357247467),(4975,1085,1355312275),(4978,1045,1358099952),(4978,1046,1355268824),(4978,1236,1357082945),(4982,1046,1357337189),(4984,1045,1357945943),(5025,1045,1357573419),(5025,1227,1357573417),(5060,1045,1357935464),(5089,1046,1355699233),(5089,1085,1355253757),(5110,1045,1357961983),(5113,1236,1357273391),(5115,1045,1357342063),(5117,1045,1357933453),(5117,1085,1355237606),(5161,1045,1358026078),(5161,1227,1357863401),(5161,1236,1358025883),(5165,1046,1356439529),(5173,1046,1357336782),(5178,1045,1357249510),(5207,1085,1355238004),(5210,1046,1357014515),(5238,1045,1355850166),(5253,1045,1355183296),(5268,1045,1357303593),(5268,1227,1357303592),(5271,1045,1357335456),(5286,1045,1357935627),(5286,1046,1357341240),(5298,1045,1358031294),(5300,1045,1356170656),(5300,1227,1356170655),(5300,1236,1356170819),(5363,1045,1355243923),(5363,1046,1357339940),(5363,1236,1357417581),(5372,1236,1357716353),(5374,1045,1358042362),(5374,1046,1357205149),(5374,1227,1357060759),(5388,1045,1357387963),(5388,1227,1357387963),(5388,1236,1357388038),(5397,1045,1355553803),(5397,1085,1355235732),(5431,1085,1355235883),(5442,1045,1357353931),(5449,1085,1355182618),(5474,1045,1356727776),(5475,1045,1357408549),(5476,1045,1357359181),(5503,1045,1357750923),(5520,1045,1357972133),(5534,1045,1357245742),(5567,1045,1358003273),(5590,1045,1357957201),(5592,1085,1355256571),(5613,1045,1357667007),(5613,1046,1356718675),(5613,1236,1356799855),(5614,1045,1357630262),(5618,1085,1355239119),(5633,1046,1357257872),(5682,1045,1357955848),(5708,1046,1357333999),(5712,1045,1357948117),(5761,1236,1357890789),(5797,1045,1357946783),(5808,1045,1357246185),(5871,1045,1355502086),(5900,1085,1355334631),(5934,1045,1355272512),(5945,1045,1357616040),(5977,1045,1357696552),(5982,1045,1357933606),(6067,1085,1355257179),(6071,1045,1357521814),(6145,1046,1356116717),(6156,1045,1358002805),(6175,1236,1357163763),(6190,1046,1357340933),(6222,1045,1358155211),(6248,1045,1357951485),(6248,1227,1357951484),(6271,7253,1357334733),(6275,1085,1355184800),(6281,1045,1355181901),(6294,11945,1357936189),(6294,11951,1357936159),(6317,1045,1357258517),(6375,1046,1357336911),(6400,1085,1355251812),(6447,1045,1357848004),(6491,1045,1358148188),(6503,1045,1357849843),(6516,1236,1357080869),(6555,1045,1355279621),(6605,1045,1357978106),(6611,1085,1355273342),(6627,1085,1355241427),(6654,1045,1357937282),(6694,1045,1355783080),(6694,1227,1355783079),(6705,1085,1355354612),(6732,1046,1357336957),(6742,1085,1355242959),(6757,1045,1357457280),(6757,1046,1356163732),(6757,1227,1357457278),(6757,1236,1357457236),(6792,1085,1355278753),(6801,1085,1355260220),(6802,1045,1355576880),(6802,1046,1357340187),(6804,1046,1357340332),(6850,1045,1357327704),(6852,1236,1357137857),(6909,1045,1357265137),(6943,1085,1355244903),(6944,1045,1355852943),(6972,1045,1357663880),(6973,1045,1358102628),(7018,1045,1357359471),(7020,1045,1357398872),(7020,1227,1357398870),(7063,1045,1357367027),(7125,1045,1358030371),(7147,1045,1357086759),(7191,1046,1357172319),(7205,1045,1357945961),(7300,1236,1357663749),(7301,1042,1357341011),(7301,1045,1357349840),(7301,1046,1357341024),(7305,1236,1357080297),(7379,1046,1356307066),(7412,1046,1357310396),(7420,1046,1357249326),(7483,1045,1356115215),(7561,1085,1355248387),(7603,1236,1355241789),(7690,1046,1357323656),(7729,1045,1355259143),(7734,1046,1355691858),(7783,1045,1357345644),(7817,1045,1357933644),(7996,1085,1355238435),(8147,1045,1355507006),(8278,1046,1357592473),(8331,1045,1358124426),(8347,1045,1355510097),(8432,1045,1358019862),(8486,1085,1355501954),(8500,1045,1357954983),(8562,1040,1357337939),(8562,1045,1357337940),(8562,1046,1357337873),(8613,1045,1355508436),(8613,1085,1355288209),(8649,1045,1357607058),(8655,1045,1357308253),(8655,1227,1357308194),(8655,5071,1358094337),(8660,1045,1357966399),(8699,1046,1357217964),(8719,1045,1357244863),(8791,1045,1357262696),(8885,1085,1355236274),(8888,1045,1357949771),(8923,1045,1357309975),(8924,1045,1357327779),(8971,1085,1355247996),(8996,1045,1357358016),(9000,1085,1355287920),(9030,1045,1357933905),(9076,1045,1357347826),(9116,1085,1355290399),(9117,1045,1355855479),(9176,1046,1355311663),(9186,1046,1357336950),(9294,1045,1357964256),(9310,1046,1357337989),(9317,1045,1355859621),(9410,1045,1357946865),(9410,1085,1355235433),(9484,1085,1355317053),(9573,1085,1355235837),(9599,1046,1357993880),(9599,1236,1357303568),(9634,1045,1357697979),(9642,1045,1357335514),(9688,1046,1357552289),(9694,1045,1357249633),(9726,1045,1355839800),(9739,1045,1355859555),(9803,1085,1355248340),(9813,1046,1355864469),(9819,1045,1357934417),(9857,1085,1355237940),(9864,1045,1358021920),(9864,1046,1357341232),(9889,1045,1355859861),(9926,1046,1357132296),(9946,1085,1355355009),(9990,1045,1356541884),(10033,1045,1357076738),(10033,1085,1355236085),(10118,1045,1358086825),(10120,1045,1357327939),(10171,1085,1355244001),(10208,1045,1357854159),(10380,1046,1357339574),(10404,1045,1357393488),(10438,1085,1355243277),(10466,1045,1356131814),(10477,1045,1357244856),(10532,1085,1355243848),(10560,1045,1355843437),(10638,1046,1357340429),(10652,1085,1355252286),(10733,1045,1357945792),(10795,1046,1356845377),(10816,1046,1357326750),(10852,1045,1355818701),(10879,1045,1357931911),(10940,1045,1357499959),(11074,1045,1357755898),(11120,1236,1355520841),(11189,1045,1357335482),(11222,1045,1357935810),(11241,1045,1357246635),(11251,1046,1357336733),(11253,1045,1357077451),(11301,1045,1357602851),(11359,1045,1357933871),(11359,1236,1355806512),(11387,1045,1357932161),(11387,1046,1357324066),(11388,1045,1357822124),(11388,1046,1357822079),(11422,1085,1355235755),(11531,1085,1355243719),(11541,1046,1357340200),(11541,1236,1356888800),(11543,1045,1358044197),(11545,1046,1357999768),(11563,1085,1355252821),(11577,1045,1357936082),(11624,1046,1357249321),(11636,15080,1355937886),(11646,1046,1357339690),(11659,1045,1357347778),(11695,1045,1357959081),(11708,1045,1358082885),(11763,1045,1355446238),(11772,1045,1355787288),(11782,1045,1357305132),(11864,1045,1357933595),(11999,1045,1357327820),(12049,1045,1357093926),(12062,1045,1356122385),(12098,1236,1355846813),(12110,1045,1357956955),(12120,1045,1357346731),(12198,1045,1357509193),(12198,2553,1356379639),(12224,1085,1355237871),(12232,1045,1357694621),(12237,1045,1357904449),(12324,1045,1357577524),(12354,1045,1357245263),(12368,1046,1357326897),(12380,1046,1355570130),(12427,1045,1357933049),(12438,1046,1357339920),(12457,1085,1355241126),(12473,1045,1358000625),(12473,1046,1357327779),(12476,1236,1355540470),(12519,1046,1357339351),(12544,1045,1357081862),(12560,1045,1358004904),(12591,1046,1357331301),(12618,1045,1357935237),(12621,1045,1355217550),(12622,1045,1357595008),(12640,1045,1357589108),(12640,1046,1357336284),(12710,1085,1355247072),(12748,1045,1357245151),(12761,1085,1355294551),(12800,1045,1357946007),(12867,1045,1357949548),(12916,1045,1357913121),(12919,1045,1357767692),(12940,1045,1357700998),(12953,1046,1357938594),(12973,1045,1355870092),(12978,1046,1357336978),(13010,1045,1357346342),(13020,1046,1357339945),(13054,1042,1357086621),(13054,1045,1357086474),(13060,1046,1357338250),(13158,1045,1357943165),(13168,1045,1358093865),(13268,1046,1355568775),(13274,1045,1357425578),(13274,1046,1356939369),(13311,1045,1355956075),(13311,1046,1357340464),(13315,1045,1357944902),(13373,14,1355264549),(13373,1045,1355845028),(13373,1085,1355272387),(13402,1045,1357328007),(13418,1046,1357340861),(13440,1085,1355245227),(13484,1085,1355262320),(13488,1045,1358098386),(13490,1085,1355294019),(13528,1085,1355237506),(13596,1085,1355240601),(13610,1045,1357938582),(13625,1045,1357263991),(13730,1045,1356123537),(13761,1045,1356125188),(13783,1045,1357328067),(13834,1045,1357938594),(13842,1045,1357933936),(13842,1085,1355237900),(13858,1046,1355675019),(13859,1045,1357935956),(13890,1045,1356728615),(13890,1085,1355264855),(13916,1045,1357947034),(13930,1046,1357341384),(13941,1046,1357338948),(13956,1045,1357946928),(13957,1045,1357249335),(13994,1045,1357324483),(14013,1046,1357339285),(14025,1236,1356979056),(14035,1045,1357325757),(14047,1046,1357337613),(14050,1045,1357325249),(14116,1045,1357946929),(14176,1045,1357245623),(14202,1045,1357352190),(14216,1085,1355243490),(14223,1085,1355247305),(14292,1046,1357339859),(14292,1236,1357350439),(14293,1046,1357322983),(14329,1085,1355178931),(14382,1045,1357959485),(14437,15093,1356734687),(14462,1046,1357338518),(14475,1045,1355272646),(14503,1085,1355339582),(14539,1045,1356467284),(14539,1046,1355616645),(14539,1227,1356467283),(14542,1045,1357664183),(14574,1046,1357255885),(14606,1045,1357336123),(14606,1046,1357336071),(14614,1045,1357937234),(14635,1045,1357335738),(14636,1236,1357078498),(14697,15094,1357268148),(14708,1045,1357263790),(14763,1085,1355244382),(14775,1085,1355280971),(14809,1085,1355240855),(14826,1045,1357590220),(14865,1045,1357966267),(14871,1045,1357874019),(14871,1085,1355246765),(14872,1045,1357959959),(14872,1236,1355626426),(14937,1045,1357245307),(14942,1046,1357336054),(14979,1236,1357330429),(15039,1085,1355246375),(15040,1045,1357346892),(15042,1045,1357074522),(15062,1045,1355235010),(15095,1045,1357351118),(15106,1085,1355270392),(15109,1045,1357951989),(15126,1045,1357408646),(15126,1227,1357408645),(15132,1236,1357174817),(15173,1085,1355237757),(15198,1045,1357249431),(15247,1046,1356754762),(15264,1045,1357668275),(15303,1045,1357957078),(15308,1045,1357939553),(15308,1046,1357336459),(15312,1046,1355176339),(15346,1045,1357359888),(15413,1085,1355249891),(15415,1046,1357323647),(15423,1085,1355196402),(15458,1045,1355233020),(15481,1045,1358017539),(15506,1045,1357356494),(15510,1045,1357954160),(15530,1045,1357263994),(15546,1042,1357339726),(15546,1046,1357339727),(15574,1045,1357342518),(15574,1227,1357342516),(15574,1236,1357342564),(15606,1045,1357245127),(15641,1045,1355181512),(15734,1045,1357348147),(15743,1045,1355868278),(15743,1046,1357338500),(15746,1045,1357956266),(15761,1045,1357332325),(15819,1085,1355236174),(15864,1046,1356567562),(15869,1045,1357932390),(15908,1045,1357954671),(15919,1085,1355237242),(16141,1046,1355821326),(16147,1045,1357950909),(16147,1046,1356690343),(16180,1045,1357624205),(16217,1045,1357337110),(16217,1046,1357336934),(16233,1045,1357246183),(16304,1046,1356252471),(16329,1045,1357980396),(16333,1045,1357365574),(16349,1045,1357920441),(16358,1045,1357675926),(16482,1045,1357364787),(16482,1227,1357364664),(16482,1236,1357364780),(16486,1085,1355344801),(16528,1045,1357346622),(16530,1046,1355909071),(16561,1085,1355260709),(16567,1045,1357324340),(16617,1046,1356593947),(16635,1045,1357929835),(16661,1042,1357336955),(16661,1046,1357336956),(16700,1046,1357323709),(16723,1045,1358091198),(16758,1085,1355256893),(16797,1046,1357663632),(16846,1046,1356352142),(16847,1045,1357640302),(16847,1046,1357640157),(16848,1045,1357863253),(16880,1045,1358162676),(16891,1045,1357249468),(16912,1045,1357125925),(16935,1085,1355507240),(16944,1045,1357931970),(16971,1045,1357377141),(17013,1085,1355439728),(17026,1046,1357329000),(17056,1085,1355262790),(17091,1085,1355249618),(17123,1045,1355507923),(17131,1045,1357999371),(17159,1045,1357076842),(17277,1045,1357929845),(17325,1045,1355848439),(17341,1045,1357085068),(17369,1046,1357339598),(17385,1046,1358018377),(17433,1236,1355183223),(17467,1046,1357340116),(17481,1046,1357338457),(17626,1046,1356438541),(17654,1085,1355260147),(17782,1046,1355991473),(17791,1046,1357216782),(17792,1045,1358111473),(17801,1085,1355242224),(17808,1046,1357336755),(17901,1236,1357333237),(17914,1045,1357327863),(17961,1046,1357329831),(17967,1085,1355277755),(17990,1045,1355854826),(18064,1085,1355508493),(18074,1085,1355259046),(18343,1045,1357600389),(18375,1045,1357442716),(18405,1045,1357353133),(18480,1045,1357942391),(18524,1045,1357260956),(18550,1045,1358005290),(18561,1236,1355549262),(18600,1045,1357416584),(18621,1046,1357339109),(18621,1085,1355239332),(18627,1085,1355273391),(18631,1045,1357341326),(18631,1046,1357341321),(18713,1045,1358002552),(18743,1045,1355548269),(18751,1045,1357599221),(18751,1236,1356120645),(18763,1046,1357336904),(18763,1085,1355189279),(18790,1045,1357499140),(18828,1045,1358126392),(18828,1046,1355639551),(18889,1046,1355176340),(18897,1045,1358093664),(18897,1085,1355277669),(18929,1045,1357327936),(18959,1045,1357935777),(18981,1045,1358049589),(18987,1045,1355860953),(19008,1085,1355327618),(19009,1045,1357329311),(19015,1085,1355238692),(19052,1046,1357247078),(19117,1045,1357335492),(19171,1045,1357742278),(19174,1045,1355852476),(19177,1046,1357337057),(19202,1045,1357358751),(19326,1046,1355494870),(19350,1045,1357495502),(19362,1045,1358021592),(19362,1085,1355246496),(19370,10908,1356288634),(19378,1046,1357336898),(19440,1046,1357132307),(19446,1045,1358150351),(19455,1046,1357340536),(19468,1045,1357691688),(19514,1046,1357339213),(19539,1045,1357522600),(19596,1045,1357130596),(19623,1236,1357671324),(19685,1045,1358014529),(19689,1045,1357327824),(19716,1045,1358006929),(19716,1227,1358006927),(19778,1045,1357335827),(19793,1085,1355236839),(19885,1045,1357136202),(19901,1085,1355279404),(19926,1045,1358022008),(19931,1045,1357335780),(20055,1085,1355248158),(20166,1046,1357338120),(20194,1046,1357338717),(20227,1045,1355786773),(20256,1046,1357377709),(20302,1045,1358025122),(20332,1045,1357313471),(20382,1085,1355247742),(20388,1085,1355236624),(20417,1045,1357347374),(20417,1236,1357346958),(20487,1046,1357340867),(20529,1045,1357933162),(20639,1045,1355273094),(20677,1045,1357335649),(20703,1045,1358124161),(20703,1046,1356242074),(20855,1046,1357337768),(20928,1045,1357939427),(20956,1046,1357472431),(21046,1045,1357407116),(21070,1046,1356709226),(21071,1045,1357370168),(21074,1046,1356277564),(21074,1236,1355809204),(21135,1046,1357724702),(21171,1045,1355253882),(21171,1227,1355253881),(21179,1045,1357310036),(21221,1045,1357258743),(21303,1236,1357309014),(21378,1046,1357340682),(21416,1045,1357931789),(21611,1045,1357664911),(21611,1085,1355249028),(21666,1045,1355856796),(21684,1045,1357353099),(21684,1227,1357353098),(21705,1046,1355331000),(21705,15068,1355345919),(21705,15069,1355428584),(21705,15106,1357937425),(21794,1085,1355245813),(21819,1046,1357839332),(21845,1045,1355872283),(21845,1046,1357340350),(21941,1045,1357749679),(21950,1236,1357715955),(21966,1045,1357749757),(22011,1045,1357099050),(22033,1045,1357933403),(22061,1045,1358129532),(22196,1045,1357335550),(22306,1045,1357694544),(22335,1046,1357338119),(22356,1046,1357336080),(22410,1045,1355861631),(22410,1227,1355861629),(22455,1045,1357253426),(22481,1046,1357339703),(22482,1042,1357336274),(22482,1046,1357336418),(22506,1045,1357518348),(22518,1046,1357336206),(22535,1045,1355864362),(22595,1085,1355263707),(22598,1040,1357336671),(22598,1042,1357336656),(22598,1045,1357336672),(22598,1046,1357336802),(22618,1085,1355238364),(22623,1045,1357933774),(22627,1046,1357337182),(22683,1045,1355835899),(22699,1045,1357017201),(22699,1227,1357017200),(22705,1045,1355867118),(22708,1046,1357324133),(22733,1046,1357338561),(22825,1045,1357938632),(22832,1236,1356144656),(22846,1046,1357336673),(22865,1236,1357529177),(22866,1045,1355185735),(22872,1085,1355241472),(22891,1236,1357117086),(22892,1045,1358134075),(22917,1045,1357945476),(22917,1046,1357340462),(22936,1045,1357352933),(22957,1085,1355382819),(22973,1045,1357964128),(22994,1085,1355284097),(23015,1045,1356207957),(23084,1045,1357987552),(23084,1085,1355210977),(23104,1046,1357254221),(23107,1045,1357376382),(23123,1045,1357246582),(23200,1046,1357337931),(23211,1045,1357497375),(23245,1045,1357354758),(23302,1085,1355276709),(23348,1045,1355176779),(23358,1045,1357307555),(23374,1085,1355351919),(23385,1236,1357457021),(23428,1046,1357340801),(23580,1045,1357324218),(23684,1045,1357083092),(23705,1045,1357946443),(23737,1046,1357340017),(23764,1045,1357974964),(23841,1045,1357335232),(23841,1227,1357335230),(23841,1236,1357335211),(23864,1046,1356909262),(23865,1085,1355262684),(23873,1045,1357075672),(23891,1085,1355238460),(23997,1045,1355414494),(24010,1085,1355446779),(24059,1045,1357671293),(24075,1236,1355253502),(24140,1046,1355883325),(24221,1045,1357445028),(24222,1046,1357758287),(24287,1085,1355424730),(24314,1045,1357347921),(24372,1046,1357340511),(24373,1046,1357336421),(24427,1045,1357670949),(24427,1236,1357169911),(24444,1045,1355854067),(24453,1045,1357450056),(24454,1045,1358026218),(24518,1045,1355509154),(24587,1045,1358048547),(24620,1045,1357089792),(24620,1236,1355809429),(24643,1045,1357622265),(24720,1045,1355194836),(24723,1045,1355571592),(25390,1045,1357931647),(25523,1045,1357603474),(25648,1045,1357939590),(25648,1227,1357939588),(25692,1046,1357324159),(25753,1085,1355260944),(25828,1045,1357325835),(25878,1045,1357939900),(25988,1045,1357372740),(26002,1045,1357934611),(26072,1045,1357327728),(26194,1045,1355836139),(26206,1085,1355345625),(26223,1045,1357849265),(26239,1045,1358022933),(26239,1046,1356411870),(26243,1085,1355264572),(26567,1046,1357336141),(26607,1045,1357933805),(26607,1085,1355241178),(26621,1046,1357338723),(26725,1042,1358120818),(26725,1045,1358120819),(26725,1085,1355237672),(26769,1046,1356625733),(26772,1046,1357333276),(26815,1236,1357333099),(26887,1045,1357331803),(26887,1085,1355413065),(26946,1046,1355464518),(27016,1045,1357258424),(27069,1045,1357080459),(27154,1045,1357701261),(27206,1045,1357938773),(27206,1046,1357906367),(27206,1085,1355247261),(27226,1046,1357339290),(27231,1085,1355448429),(27314,1046,1357337861),(27339,1085,1355238500),(27374,1045,1357675206),(27374,1046,1357336350),(27459,1046,1355734950),(27481,1085,1355247262),(27495,1045,1357955778),(27499,1085,1355273249),(27524,1045,1357075272),(27549,1085,1355238539),(27569,1046,1357339466),(27580,1045,1357597150),(27594,1045,1357347017),(27604,1046,1357244511),(27739,1045,1357074114),(27830,1046,1357819451),(27871,1045,1356651103),(27953,1085,1355237089),(27996,1045,1357731670),(28026,15056,1355199565),(28063,1045,1357404867),(28095,1085,1355240282),(28153,1046,1357249329),(28225,1045,1357965209),(28323,1046,1356781611),(28361,1236,1355865932),(28527,1085,1355238224),(28546,1085,1355235489),(28549,1045,1357335589),(28557,1045,1357867090),(28587,1045,1355763348),(28656,1045,1357347176),(28671,1045,1355850830),(28671,1227,1355850829),(28701,1045,1357573718),(28716,1085,1355419655),(28839,1045,1358018384),(28878,1046,1357339233),(28925,1045,1357948103),(28950,1045,1357352422),(29042,1045,1355957410),(29052,1045,1357334276),(29095,1045,1357321469),(29142,1045,1357930220),(29177,1045,1357950270),(29196,1046,1357337995),(29207,1045,1357957777),(29224,1085,1355255613),(29382,1046,1357254379),(29406,1045,1357010797),(29406,1227,1357010796),(29413,1045,1358011857),(29413,1227,1356100071),(29563,1046,1357337302),(29571,1046,1357338307),(29573,1046,1357276249),(29599,1045,1357246110),(29672,1045,1357327889),(29719,1045,1357970589),(29750,1045,1357331733),(29774,1045,1357345677),(29813,1236,1357074115),(29864,1236,1357173429),(29878,1045,1355784937),(29935,1045,1357142898),(29935,1085,1355279263),(30014,1085,1355245773),(30050,1045,1357115009),(30152,15068,1355376195),(30157,1045,1355537681),(30159,1045,1358093144),(30171,1046,1357336154),(30239,1085,1355294798),(30289,1085,1355244337),(30293,1046,1357340131),(30369,1045,1357335937),(30369,1227,1357275420),(30369,1236,1357275393),(30409,1085,1355240040),(30414,1045,1357951279),(30433,1046,1357153297),(30437,1085,1355257546),(30446,1085,1355240249),(30468,1045,1355177870),(30477,1046,1357337595),(30527,1046,1357938078),(30536,1085,1355259611),(30538,1045,1357348126),(30605,1046,1356481205),(30854,1045,1357077378),(30863,1085,1355439761),(30966,1236,1355857310),(31011,1045,1357616804),(31041,1085,1355289611),(31066,1045,1355567638),(31084,1045,1358137071),(31084,1046,1357325020),(31095,1045,1356631200),(31104,1045,1357946434),(31110,1236,1355241652),(31161,1045,1357681632),(31161,1046,1357682069),(31161,1227,1357681628),(31161,1236,1357681732),(31168,1045,1355890319),(31168,1046,1357335997),(31189,1236,1358053500),(31189,15044,1355176876),(31203,1045,1357358765),(31223,1046,1357341244),(31231,1045,1357245403),(31240,1085,1355255706),(31270,1046,1357337055),(31378,1045,1357334131),(31396,1085,1355245926),(31460,1046,1357335099),(31480,1045,1357075673),(31562,1085,1355237484),(31575,1085,1355242036),(31716,1045,1357687447),(31879,1045,1357255245),(31956,1046,1357326820),(31997,1045,1356105318),(31997,1227,1356105311),(32114,1045,1358086695),(32114,1046,1357339276),(32114,1227,1356840625),(32114,1236,1357690803),(32143,1045,1357947791),(32144,1085,1355253021),(32164,1045,1357268286),(32229,1045,1355867135),(32294,1045,1357754428),(32335,1045,1357364274),(32368,1046,1357338490),(32368,1085,1355244752),(32422,1045,1357946611),(32481,1085,1355238854),(32518,1045,1357338078),(32518,1046,1357338398),(32518,1227,1357338075),(32547,1085,1355254344),(32591,1045,1355608581),(32680,1236,1357325030),(32763,1046,1357337311),(33192,1045,1357937300),(33198,1045,1356939339),(33198,1227,1356939337),(33198,1236,1356939423),(33238,1045,1357359077),(33253,1045,1357952985),(33284,1045,1357586709),(33284,1046,1356809361),(33310,1045,1357958220),(33419,1045,1356018979),(33419,1227,1356018978),(33445,1045,1357693593),(33496,1236,1355273882),(33592,1085,1355274287),(33616,1045,1357259381),(33616,1227,1357259277),(33673,1045,1357943410),(33676,1045,1357654079),(33687,1045,1357922008),(33724,1045,1357353927),(33846,1045,1357358358),(33886,1236,1356016021),(34209,1045,1357251224),(34504,1045,1357994842),(34516,1046,1357336624),(34534,1045,1358020602),(34584,1085,1355241425),(34609,1046,1355397261),(34666,1045,1357953820),(34681,1045,1357358297),(34681,1046,1357358270),(34687,1046,1357341482),(34768,1046,1357338516),(34780,1045,1357329360),(34780,1085,1355239605),(34800,1045,1357077320),(34834,1045,1357082956),(34844,1045,1357936614),(34844,1046,1357326871),(34870,1045,1357677627),(34870,1046,1356316468),(34938,1085,1355197900),(34939,1046,1357336444),(34961,1045,1357110276),(34980,1045,1357353285),(35020,1046,1357336909),(35106,1045,1357938131),(35106,1085,1355242093),(35137,1045,1357957412),(35137,1046,1356236614),(35166,1045,1357365816),(35325,1045,1355194670),(35355,1045,1356413930),(35429,1045,1355766476),(35429,1227,1355766474),(35429,15070,1355448868),(35499,1045,1356800112),(35561,1046,1357339876),(35595,1045,1357663188),(35595,1046,1357336850),(35681,1045,1356835255),(35890,1045,1358108579),(35890,1046,1358109527),(35958,1045,1357348664),(35966,1045,1357945198),(35996,1085,1355245227),(36014,1085,1355248690),(36029,1045,1357231843),(36029,1046,1357336056),(36049,1045,1355871593),(36085,1039,1357676282),(36085,1046,1357676284),(36092,1045,1355843337),(36119,1046,1357337359),(36201,1046,1357337764),(36226,1046,1357337941),(36231,1085,1355237388),(36244,1045,1357592616),(36244,1046,1357337687),(36251,1045,1357373700),(36251,1046,1357339425),(36251,1085,1355285290),(36342,1236,1357084756),(36426,1085,1355245241),(36436,1045,1357259280),(36477,1085,1355248653),(36524,1045,1357933376),(36524,1085,1355241144),(36608,1046,1357338996),(36624,1085,1355243079),(36655,1045,1357933074),(36766,1045,1357347844),(36824,1045,1357944015),(36897,1085,1355245538),(36972,1045,1356106797),(36972,1227,1356106797),(37063,1045,1358006235),(37097,1045,1357348525),(37186,1085,1355419645),(37364,1045,1357496267),(37364,1085,1355239657),(37388,1042,1358084490),(37388,1045,1358084493),(37734,1045,1357359155),(37778,1045,1355242471),(37778,1085,1355242454),(37781,1045,1357671229),(37941,1045,1357624305),(37941,1046,1357624312),(38030,1045,1355812936),(38196,1045,1357334088),(38196,1227,1357334087),(38337,1046,1357336174),(38363,1045,1357967942),(38412,1085,1355283616),(38435,1045,1355845424),(38514,1042,1357336529),(38514,1046,1357336530),(38514,15091,1357244868),(38524,1045,1358097927),(38583,1045,1358001644),(38583,1046,1357337245),(38608,1045,1357949477),(38617,1236,1357527667),(38632,1085,1355188870),(38693,1045,1357677294),(38797,1045,1355836803),(38801,1045,1357352832),(38831,1045,1357943896),(38836,1045,1357359339),(38836,1227,1357359251),(38836,1236,1358003064),(38900,1085,1355250451),(38910,1045,1357933030),(38910,1085,1355344941),(38988,1085,1355246620),(38998,1045,1356124028),(38998,1085,1355250308),(39004,1045,1357080201),(39005,1046,1357337690),(39016,1045,1357327942),(39048,1045,1357366131),(39088,1045,1357967532),(39170,1045,1356971371),(39189,1045,1357673194),(39363,1046,1357340305),(39441,1045,1357352768),(39525,1045,1356971831),(39565,1045,1356136935),(39632,1045,1357502896),(39727,1045,1357583107),(39794,1045,1357684690),(39870,1085,1355237861),(40065,1085,1355239459),(40208,1045,1357941954),(40213,1045,1357598026),(40373,1045,1357618310),(40564,1045,1357087661),(40636,1045,1357933454),(40720,1045,1357933850),(40805,1085,1355235400),(40817,1045,1357335875),(40817,1046,1357335941),(40860,1045,1357249327),(40860,1046,1357249331),(40877,1085,1355275171),(40909,1045,1356126436),(40966,1046,1357337576),(41010,1045,1357335726),(41062,1045,1355186265),(41079,1045,1357622421),(41080,1045,1357322023),(41332,1045,1355508491),(41332,1046,1356105878),(41332,1236,1356299173),(41640,1045,1357401215),(41683,1045,1357935792),(41719,1045,1355819258),(41719,1227,1355819257),(41734,1085,1355262988),(41840,1085,1355301401),(41895,1045,1356138237),(41914,1085,1355239461),(41942,1045,1356123534),(41946,1046,1356458178),(42671,1045,1355839910),(42676,1045,1357662671),(42734,1045,1357841561),(42735,1045,1357939544),(42751,1085,1355241148),(42760,1045,1358019939),(42770,1045,1356657097),(42834,1045,1355192096),(42849,1046,1357335155),(42894,1045,1357746483),(42911,1045,1357489034),(42974,1045,1357352418),(42978,1046,1357337974),(43033,1045,1357335555),(43059,1046,1357346400),(43075,1045,1358083088),(43075,1046,1358083194),(43087,1085,1355235963),(43141,1046,1357083621),(43144,1045,1357358643),(43153,1046,1357249339),(43169,1045,1357081566),(43220,1045,1357926042),(43241,1045,1357347668),(43359,1045,1357353294),(43371,1045,1357246273),(43371,1046,1357339022),(43491,1045,1357953580),(43501,1045,1357328009),(43522,1045,1357359777),(43614,1045,1355886270),(43622,1045,1357737545),(43622,1046,1356383678),(43622,1227,1356683896),(43634,1045,1357935031),(43635,1045,1356532975),(43635,1085,1355489132),(43743,1085,1355236942),(43748,1045,1358091064),(43758,1085,1355243121),(43778,1045,1358017720),(43778,1046,1358017877),(43957,1045,1357680143),(43964,15094,1357075562),(44155,1046,1357340477),(44157,1045,1357077268),(44212,1045,1355808801),(44246,1236,1357157221),(44247,1045,1357345687),(44320,1045,1357086391),(44469,1236,1355813767),(44731,1045,1358009534),(44818,1045,1356473097),(44858,1085,1355240931),(44859,1045,1357588065),(44927,1045,1357968556),(44927,1227,1357968555),(44945,1045,1357587298),(45019,1085,1355244697),(45036,1085,1355248867),(45047,1046,1357326888),(45137,1045,1357248646),(45144,1040,1357346278),(45144,1045,1357346279),(45144,1046,1357337624),(45163,1045,1357933178),(45325,1085,1355239034),(45335,1045,1357938511),(45381,1045,1357852033),(45386,1045,1358026579),(45386,1046,1357336364),(45401,1045,1357348588),(45447,1045,1357359149),(45471,1046,1357323666),(45471,1085,1355241670),(45500,1045,1357527172),(45547,1045,1357961226),(45660,1045,1357226076),(45800,1045,1355507180),(45825,1046,1357336864),(45838,1085,1355262650),(45843,1085,1355361850),(45906,1045,1357334079),(46007,1085,1355243650),(46055,1045,1355531541),(46073,1045,1355836868),(46095,1045,1358012599),(46117,1045,1355429430),(46117,1236,1357386560),(46118,1045,1357953258),(46277,1045,1357986985),(46359,1045,1357754514),(46429,1045,1357328040),(46516,1236,1355868516),(46553,1045,1355619506),(46553,1085,1355250443),(46576,1045,1355513287),(46591,1045,1358051899),(46595,1045,1357938635),(46603,1045,1356125827),(46632,1046,1357336755),(46819,1045,1357607094),(46848,1045,1357335436),(46898,1045,1357373381),(46941,1045,1357764940),(46941,1236,1357076049),(46961,1045,1357940309),(46961,1046,1357727421),(47008,1085,1355250731),(47017,1046,1357336217),(47017,1085,1355236692),(47134,1046,1357326907),(47154,1085,1355240806),(47211,1085,1355329449),(47283,1045,1357854291),(47283,15094,1357856054),(47288,1045,1358001258),(47404,1045,1357316821),(47427,1045,1357263972),(47537,1045,1358011050),(47552,1046,1357338430),(47602,1045,1357341150),(47602,1046,1357341151),(47602,1085,1355183357),(47644,1046,1357337259),(47649,1045,1357341231),(47649,1046,1357341409),(47665,1045,1356991406),(47665,1236,1357062409),(47734,1046,1356754160),(47753,1045,1357318656),(47753,1227,1357318655),(47753,1236,1357322869),(47774,1085,1355247066),(47809,1085,1355253779),(47883,1045,1358139963),(47900,1045,1356531066),(47900,1227,1356531065),(47900,1236,1356531050),(47932,1045,1357346536),(47980,1046,1357337004),(48069,1046,1357270726),(48082,1045,1357491265),(48115,1085,1355236638),(48136,1045,1357358158),(48147,1085,1355236823),(48214,1045,1358131023),(48240,1045,1357931862),(48253,1045,1355609714),(48253,1046,1355465022),(48384,1085,1355270929),(48438,1045,1357344949),(48438,1227,1357344949),(48438,1236,1357344917),(48444,1046,1357909707),(48616,1045,1357276997),(48681,1045,1355350109),(48690,1045,1355970734),(48726,1045,1357628432),(48735,1045,1357944323),(48840,1085,1355246803),(48881,1236,1355950269),(48901,1085,1355237649),(48973,1045,1357143813),(48996,1045,1358041333),(49023,1042,1357337308),(49023,1046,1357337708),(49023,1236,1357401827),(49051,1085,1355244652),(49238,1085,1355235661),(49430,1085,1355242180),(49451,1046,1355883336),(49457,1045,1357705422),(49482,1046,1357343597),(49515,1046,1356631358),(49544,1045,1355516522),(49544,1046,1357338241),(49662,1045,1357940928),(49662,1046,1357337578),(49670,1045,1357256191),(49867,1046,1355423460),(49870,1045,1357942718),(49877,1045,1357228961),(49940,1046,1357325157),(50063,1045,1357316576),(50070,1045,1355810728),(50188,1045,1355182734),(50200,1046,1357339616),(50232,1045,1357328028),(50243,1046,1357336758),(50263,1085,1355245033),(50274,1045,1357245420),(50322,1045,1355524296),(50342,1046,1357337494),(50375,1045,1357327847),(50412,1046,1357138946),(50423,1045,1357608550),(50492,1046,1357336739),(50562,1085,1355277315),(50662,1045,1357060006),(50704,1046,1355176328),(50715,1045,1358008786),(50725,1045,1358007623),(50749,1045,1357618418),(50749,1046,1357705203),(50752,1045,1357328055),(50799,1045,1355292424),(50799,1227,1355292421),(50839,1045,1357901442),(50865,1045,1355921986),(50910,1045,1357341498),(50936,1045,1357698957),(50980,1045,1357582515),(50993,1045,1358127122),(50994,1045,1357329135),(51027,1045,1357945964),(51038,1045,1357964592),(51044,1085,1355241525),(51045,1045,1357410757),(51045,1227,1357410755),(51045,1236,1357410743),(51087,1085,1355243589),(51111,1045,1358017006),(51111,1085,1355248342),(51128,1045,1357255151),(51132,1085,1355243524),(51149,1085,1355235812),(51159,1045,1357354152),(51170,1045,1357936755),(51197,1085,1355264472),(51214,1045,1357347842),(51296,1045,1358153073),(51296,1046,1356338269),(51460,1236,1355809578),(51567,1045,1355400706),(51612,1046,1357336362),(51641,1085,1355487414),(51680,1045,1357352150),(51793,1046,1357339765),(51913,1046,1356624860),(51942,1045,1355322451),(52049,1045,1356307040),(52101,1085,1355257988),(52116,1045,1358002975),(52116,1236,1357350646),(52152,1045,1357945130),(52220,1045,1356277827),(52224,1045,1357359626),(52232,1045,1355749214),(52274,1085,1355254033),(52444,1045,1357618541),(52479,1045,1357335534),(52512,1045,1357372012),(52520,1045,1357366510),(52544,1045,1357245516),(52624,1045,1357444121),(52624,1085,1355242336),(52624,1227,1357444121),(52685,1236,1355512528),(52729,1045,1356121874),(52753,1045,1355811559),(52806,1046,1357339539),(52829,1085,1355239331),(52865,1045,1356146709),(52865,1227,1356146708),(53130,1236,1355830972),(53142,1236,1357237507),(53259,1085,1355256727),(53297,1045,1357347023),(53297,1085,1355268612),(53310,1045,1357837786),(53310,1236,1357837751),(53321,1045,1358136888),(53506,1045,1356182735),(53511,1046,1357336951),(53512,1046,1357337449),(53555,1045,1358015131),(53752,1085,1355285880),(53919,1045,1357333295),(53919,1227,1357333294),(53919,1236,1357333429),(53933,1085,1355247112),(53999,1045,1355844194),(54055,1085,1355413726),(54149,1045,1357310899),(54195,1085,1355242363),(54294,1045,1357233997),(54314,1085,1355267734),(54448,1045,1357345667),(54507,1085,1355496221),(54515,1085,1355284983),(54560,1045,1357941667),(54571,1085,1355239848),(54596,1046,1357337455),(54686,1045,1357491941),(54686,1227,1357491939),(54713,1045,1357309072),(54714,1045,1357959057),(54933,1236,1357332350),(54998,1045,1358018273),(55018,1046,1357254250),(55050,1046,1357576482),(55069,1045,1357937142),(55069,1085,1355314884),(55212,1045,1355512469),(55287,1085,1355925158),(55316,1045,1357952270),(55435,1045,1357358547),(55623,1236,1357591139),(55633,1046,1357253669),(55786,1045,1357327971),(55832,1045,1356832200),(55850,1045,1358008763),(55858,1045,1357937965),(55858,1085,1355257202),(55913,1045,1357933280),(55963,1085,1355253383),(55977,1045,1357363495),(56023,1085,1355278066),(56123,1046,1357338379),(56174,1045,1355972281),(56174,1085,1355239729),(56176,1045,1357106587),(56184,1045,1356152934),(56184,1046,1357340394),(56247,1045,1357593558),(56362,1045,1357684091),(56436,1085,1355236238),(56489,1046,1357336648),(56530,1045,1357846657),(56594,1045,1355258078),(56594,1227,1355258078),(56644,1085,1355240326),(56645,1045,1357331078),(56645,1227,1357331077),(56647,1045,1358005506),(56705,1046,1357341427),(56722,1085,1355356093),(56726,1046,1357339870),(56803,1045,1357319211),(56803,1236,1357319280),(56872,1045,1357934088),(56896,1045,1357352662),(56896,1085,1355369661),(56908,1045,1357932606),(56999,1045,1358136022),(56999,1046,1358136011),(57016,1045,1357436567),(57023,1045,1357951289),(57032,1045,1357276614),(57032,1227,1357276613),(57094,1046,1358122219),(57101,1085,1355349603),(57139,1045,1357949547),(57170,1045,1357666498),(57170,1046,1357323614),(57191,1045,1357934079),(57288,1045,1357466380),(57288,1046,1357816774),(57325,1045,1357967685),(57329,1045,1358096217),(57338,1046,1357340353),(57344,1085,1355249155),(57370,1085,1355239575),(57407,1045,1357359940),(57415,1045,1357939342),(57437,1045,1357957326),(57507,1236,1357489190),(57571,1046,1357324754),(57575,1085,1355186127),(57600,1046,1357338195),(57631,1085,1355300482),(57634,1045,1357948857),(57644,1046,1357336985),(57652,1236,1357367776),(57736,1045,1357563123),(57747,1236,1357140650),(57789,12845,1355995010),(57870,1045,1357945085),(57965,1045,1357249901),(58000,1045,1357696257),(58001,1045,1355861291),(58035,1085,1355244795),(58052,1085,1355245306),(58078,1045,1355523485),(58078,1085,1355242566),(58175,1085,1355236910),(58205,1085,1355272525),(58289,1045,1357075921),(58345,1045,1355523490),(58356,1085,1355179451),(58406,1045,1357755613),(58429,1236,1357163350),(58480,1045,1355812053),(58485,1045,1357250898),(58530,1045,1357947978),(58643,1045,1357329129),(58643,1046,1357340018),(58726,1042,1357337620),(58726,1046,1357337621),(58766,1045,1357327878),(58819,1085,1355246755),(59046,1045,1357330232),(59150,1045,1358129434),(59208,1045,1357327963),(59403,1045,1356123056),(59440,1085,1355236067),(59498,1045,1357323220),(59498,1046,1357323621),(59573,1045,1357663106),(59607,1046,1357338799),(59607,1085,1355236646),(59660,1045,1357972649),(59663,1236,1357401633),(59695,1045,1355807508),(59695,1085,1355358492),(59700,1085,1355239872),(59789,1045,1358005805),(59823,1045,1357374194),(59830,1085,1355235638),(59864,1085,1355238065),(59898,1046,1357560951),(59914,1045,1355519241),(59947,1046,1357338868),(59959,1045,1356037428),(60015,1046,1357340472),(60021,1236,1356095835),(60098,1045,1357328031),(60177,1085,1355238621),(60260,1045,1355860340),(60299,1046,1357336463),(60317,1236,1357331071),(60343,1045,1357348554),(60360,1046,1357327153),(60363,1045,1356157557),(60454,1045,1357347352),(60465,1045,1356131069),(60502,1045,1357949117),(60502,1046,1357337333),(60505,1085,1355274878),(60587,1236,1355540598),(60594,1045,1355872326),(60594,1085,1355260920),(60595,1045,1357963682),(60606,1085,1355345690),(60613,1045,1357371059),(60619,1045,1358003997),(60619,1046,1357336862),(60648,1046,1356998117),(60820,1040,1355848169),(60820,1045,1355848145),(60946,1045,1357608969),(60946,15107,1357950147),(60966,1085,1355250832),(61163,1046,1357650046),(61305,15070,1355506991),(61387,1045,1356173190),(61387,1046,1357340444),(61442,1085,1355340588),(61520,1045,1357172605),(61714,1045,1355193522),(61776,1045,1357632012),(61781,1045,1357850209),(61809,1046,1355338618),(61888,1045,1357249334),(61936,1045,1357359306),(61950,1236,1355202082),(61981,1045,1357349893),(62074,1045,1356572619),(62107,1085,1355263773),(62114,1085,1355185402),(62165,1045,1357131027),(62178,1046,1355843656),(62178,1236,1355843558),(62215,1045,1356973595),(62227,1045,1355808167),(62267,1046,1357337988),(62285,1045,1357342617),(62285,1046,1357339734),(62289,1046,1357338227),(62300,1045,1355189734),(62341,1046,1357254578),(62359,1045,1357973968),(62359,1236,1357168792),(62445,1045,1356142594),(62446,1045,1357938133),(62521,1045,1357255891),(62560,1045,1358071004),(62574,15051,1355278752),(62642,1085,1355283991),(62829,1236,1357670378),(62964,1085,1355239895),(63079,1045,1357359931),(63151,1045,1358004465),(63211,1236,1357325219),(63328,1236,1357324465),(63337,1045,1355863448),(63383,1045,1357353456),(63440,1236,1357335759),(63441,1085,1355243518),(63502,1045,1357352545),(63532,1045,1357476187),(63534,1045,1357353150),(63708,1085,1355243617),(63766,1045,1357934063),(63773,1045,1355431110),(63773,1085,1355238676),(63782,1085,1355319130),(63796,1045,1357673409),(63815,1046,1357338180),(63833,1045,1357076545),(63838,1085,1355279663),(63857,1085,1355250983),(63996,1085,1355240747),(64006,1046,1357768077),(64036,1045,1355835065),(64107,1085,1355268288),(64156,1045,1357940029),(64248,1045,1357327883),(64253,1045,1355511873),(64259,1045,1357358387),(64259,1085,1355451899),(64304,1045,1357077362),(64440,1046,1357337358),(64529,1045,1357245455),(64610,1236,1357327683),(64623,1045,1357098263),(64659,1046,1357817485),(64779,1045,1358026410),(64780,1045,1357859691),(64799,1045,1357618185),(64805,1085,1355458718),(64843,1046,1357337492),(64858,1085,1355368497),(64893,1046,1357337591),(64895,1046,1357337394),(64916,1045,1358095619),(64926,1046,1357336751),(64968,1046,1357336244),(64978,1045,1357932301),(65021,1045,1357245516),(65046,1045,1357263268),(65160,1045,1357434583),(65160,1227,1357434581),(65171,1040,1356795453),(65171,1045,1356795453),(65220,1045,1358038688),(65366,1045,1357358826),(65375,1085,1355246296),(65406,1085,1355241049),(65579,1045,1355259736),(65579,1085,1355259721),(65588,1046,1355855218),(65588,1085,1355252155),(65603,1046,1357337411),(65652,1045,1355890128),(65929,1045,1357334198),(65930,1046,1357528401),(66126,1085,1355238758),(66237,1045,1358126386),(66498,1085,1355238472),(66646,1045,1357337443),(66646,1046,1357337477),(66667,1045,1357084314),(66856,1045,1355247280),(66856,1085,1355247265),(67051,1045,1356133126),(67122,1045,1355599362),(67143,1085,1355244980),(67170,1046,1356107945),(67170,1085,1355239843),(67215,1046,1357338695),(67253,1045,1357936622),(67261,1045,1357674061),(67268,1045,1356103073),(67268,1085,1355244858),(67268,3049,1356103033),(67268,11556,1356103022),(67328,1045,1357762784),(67387,1085,1355240163),(67419,1236,1357330192),(67480,1085,1355249991),(67493,1046,1357339638),(67524,1085,1355276717),(67762,1046,1357680328),(67821,1045,1357327965),(67841,1045,1357259396),(67862,1045,1356155344),(67862,1085,1355178948),(67907,1046,1357254340),(67907,1236,1357328855),(67949,1085,1355243208),(67958,1045,1355814089),(68059,1045,1357337644),(68138,1042,1357340604),(68138,1046,1357340624),(68142,1085,1355250517),(68255,1045,1357365222),(68310,1045,1355841349),(68322,1045,1355515656),(68334,1046,1357333266),(68426,1045,1356131845),(68432,1085,1355256691),(68477,1045,1355809810),(68516,1045,1357340927),(68516,1046,1357340926),(68516,1236,1357662522),(68747,1045,1357365922),(68798,1046,1355176170),(68879,1046,1357340664),(68968,1045,1355835959),(69231,1045,1357660322),(69322,1085,1355240215),(69327,1045,1357983819),(69454,1045,1357353974),(69467,1046,1357338304),(69480,1045,1358004937),(69597,1045,1355820924),(69695,1085,1355367476),(69897,1045,1357933286),(70052,1045,1357076346),(70082,1045,1357944192),(70082,1236,1357944187),(70213,1045,1357353729),(70217,1045,1357767136),(70307,1045,1355876759),(70347,1045,1358039806),(70428,1046,1357336202),(70444,1046,1357243751),(70475,1045,1358018926),(70613,1045,1356196279),(70624,1045,1357934985),(70723,1045,1356800760),(70876,1045,1355634578),(70896,1045,1357269894),(70972,1046,1357326883),(71080,1045,1357952586),(71227,1045,1355835392),(71284,1045,1357774512),(71298,1045,1355188076),(71368,1045,1357936417),(71466,1045,1357112866),(71468,1045,1355183630),(71506,1045,1357961553),(71506,1046,1357637788),(71517,1236,1357074507),(71600,1045,1357264130),(71662,1046,1357336100),(71714,1045,1355238460),(71773,1045,1357309318),(71773,1046,1357041526),(71895,15105,1357935676),(71923,1045,1356062510),(72092,1085,1355237194),(72149,2881,1357674788),(72233,1045,1357612273),(72233,1236,1357332291),(72488,1085,1355253177),(72520,1045,1357367068),(72549,1046,1357341338),(72570,1236,1356740989),(72601,1085,1355252341),(72641,1045,1355179161),(72649,1045,1356123298),(72677,1045,1358093131),(72677,1046,1357662063),(72686,1046,1357336965),(72733,1045,1358082665),(72758,1045,1357686766),(72781,1045,1357933160),(72795,1046,1357337478),(72871,1045,1357252285),(73035,1045,1357249416),(73110,1046,1357337827),(73166,1045,1356657571),(73172,1045,1356120413),(73172,1085,1355251130),(73181,1046,1357336918),(73208,1085,1355269029),(73248,1046,1357254265),(73296,1045,1357942861),(73354,1085,1355246794),(73367,1045,1358016669),(73433,1045,1357245297),(73681,1236,1355838334),(73694,1045,1356119079),(73694,1085,1355262499),(73737,1045,1355761298),(73827,1045,1355962513),(73952,1085,1355264122),(74024,1045,1357917544),(74076,1085,1355247571),(74093,1045,1355528693),(74093,1085,1355443116),(74232,15039,1355968304),(74232,15078,1355955902),(74237,1045,1356140308),(74237,1085,1355255746),(74241,1045,1355859238),(74351,1045,1356974446),(74370,1085,1355278603),(74371,1046,1358060521),(74384,1045,1358087879),(74409,1045,1357962084),(74422,1046,1355883663),(74431,1045,1357365061),(74519,1046,1357553991),(74519,1236,1356263629),(74535,1085,1355304169),(74650,1046,1357336791),(74699,1045,1357662678),(74736,1045,1355514656),(74820,1045,1357328017),(74828,1046,1355728456),(74896,1045,1357815100),(74961,1045,1357932503),(75064,1045,1356972084),(75150,1045,1356123788),(75212,1045,1355721016),(75215,1045,1357852459),(75224,1236,1357327405),(75290,1045,1356207021),(75290,1085,1355246779),(75339,1045,1358136364),(75339,1046,1358135899),(75368,1045,1357077669),(75369,1045,1357959667),(75620,1085,1355243648),(75632,1085,1355263686),(75667,1085,1355458451),(75785,1046,1355559771),(75874,1045,1357942790),(75949,1085,1355371011),(75967,1045,1357943376),(76071,1045,1355240735),(76071,1085,1355239598),(76084,1045,1357351205),(76084,1236,1355509061),(76098,1085,1355240439),(76104,1085,1355253746),(76126,1045,1355789830),(76127,1045,1357961478),(76257,1042,1357337849),(76257,1046,1357337850),(76264,1085,1355265995),(76473,1045,1357247723),(76538,1045,1357077718),(76673,1085,1355243071),(76852,1045,1357413458),(76882,1045,1357941183),(77160,1085,1355246134),(77215,1045,1357948118),(77428,1045,1358099074),(77428,1046,1357336208),(77453,1045,1358089684),(77652,1040,1357980561),(77652,1042,1357980421),(77652,1045,1357982228),(77656,1045,1355887357),(77752,1045,1358113240),(77791,1045,1357856994),(77842,1045,1357359339),(77864,1045,1357247349),(77877,1045,1357958263),(77880,1046,1355656913),(77927,1085,1355274224),(77946,1045,1357088522),(77988,1045,1357324260),(78019,1045,1357948238),(78027,1045,1357421749),(78027,1085,1355253903),(78027,1227,1357421748),(78027,1236,1357421769),(78097,1085,1355238801),(78120,1045,1357329493),(78120,1227,1357329492),(78120,1236,1357330231),(78135,1085,1355235435),(78166,1085,1355197543),(78206,1046,1357336316),(78375,1045,1358090888),(78384,1046,1357340160),(78418,1046,1357336273),(78461,1045,1357938334),(78501,1085,1355237258),(78503,1045,1357792266),(78530,1045,1357123576),(78651,1045,1357936610),(78651,1085,1355235976),(78662,1236,1355231659),(78699,1046,1357341431),(78791,1045,1356139219),(78935,1046,1357880551),(79000,1045,1357247854),(79005,1085,1355285403),(79063,1045,1355193631),(79088,1085,1355274451),(79097,1045,1355837937),(79260,1045,1357951002),(79311,1045,1357953202),(79342,1085,1355256356),(79351,1045,1357703969),(79457,1045,1357954718),(79466,1045,1357327881),(79816,1085,1355268641),(79867,1085,1355237671),(79976,1045,1357249105),(79988,1045,1357327977),(80145,1085,1355236932),(80361,1045,1357679033),(80379,1046,1357332114),(80452,1046,1357339185),(80621,1045,1355807117),(80718,1045,1357077350),(80732,1046,1357324160),(80972,1085,1355237771),(81229,1045,1357963519),(81658,14027,1357075341),(81674,1045,1357251225),(81924,1045,1357363946),(81928,1045,1357945375),(82143,1045,1355857072),(82184,1045,1357248019),(82238,1045,1357346934),(82283,1085,1355252633),(82328,1046,1357339130),(82871,1045,1358116469),(83243,1045,1355185492),(83243,1227,1355185491),(83360,1046,1355176339),(83498,1045,1357949508),(83502,1045,1355870329),(83546,1045,1357612123),(83573,1046,1355384411),(83722,1045,1357371171),(83722,1046,1355298354),(83722,1085,1355298095),(83799,1085,1355236636),(83836,1046,1357604046),(83866,1045,1355203557),(84070,1046,1357515125),(84219,1042,1357337958),(84219,1046,1357337959),(84384,1046,1357324089),(84427,1045,1355535521),(84469,1045,1357947376),(84537,1045,1355807359),(84629,1045,1357074398),(84758,1046,1357254783),(85382,1085,1355419996),(85445,1046,1357759446),(85613,1045,1357954837),(85694,1045,1357943498),(86280,1046,1357326921),(86461,1045,1358124342),(86508,1045,1357859920),(86508,1046,1357338721),(86830,1045,1357226232),(87043,1045,1357370775),(87129,1045,1357933683),(87249,1046,1358109740),(87250,1046,1357338285),(87304,1045,1358093580),(87304,1085,1355238386),(87364,1045,1358029448),(87364,1046,1357340278),(87494,1045,1357933704),(87528,1046,1357758147),(87574,1045,1357541801),(87606,1045,1357768560),(87610,1045,1357584921),(87621,1045,1357358586),(87647,1045,1357323783),(87801,1045,1357614117),(88106,1046,1357341203),(88134,1046,1357339307),(88180,1045,1355933552),(88206,1045,1357942773),(89186,1045,1357747956),(89286,1045,1357249149),(89335,1046,1357341084),(89472,1085,1355244140),(89494,1085,1355251273),(89530,1045,1357682661),(89565,1046,1357336296),(89591,1085,1355244632),(89598,1046,1357338864),(89683,1085,1355235892),(89762,1085,1355238426),(89825,1236,1357323917),(89870,1045,1357335782),(89870,1046,1357336198),(89875,1045,1356210331),(89933,1045,1357341223),(89933,1046,1357341218),(90012,1045,1357934644),(90028,1046,1356300934),(90131,1045,1356135424),(90177,1046,1357604047),(90216,1045,1357782039),(90246,1046,1357341488),(90307,1045,1357244377),(90317,1046,1357339512),(90340,1045,1357229211),(90358,1045,1355807616),(90503,1045,1357366257),(90573,1045,1357933090),(90578,1085,1355189706),(90635,1046,1357275086),(90636,1085,1355241996),(90639,1236,1355844407),(90656,1045,1355177589),(90658,1045,1357082705),(90658,1046,1357339528),(90718,1045,1357976254),(90742,1085,1355292298),(90799,1085,1355239015),(90909,1045,1357748039),(90980,1045,1355866515),(91094,1045,1355190372),(91099,1045,1357327897),(91196,1085,1355280953),(91308,1045,1357833503),(91436,1045,1357327916),(91526,1085,1355266969),(91536,1236,1357684203),(91565,1045,1357327914),(91619,1045,1358119558),(91619,1046,1357338197),(91658,1045,1357244748),(91667,1085,1355267916),(91674,1045,1355820396),(91706,1045,1357334306),(91716,1045,1357335499),(91773,1236,1357326322),(91794,1046,1357340221),(91824,1045,1358015537),(91845,1046,1357336132),(91884,1045,1357077928),(91919,1045,1357908334),(91937,1085,1355281136),(91975,1085,1355236343),(92008,1046,1357324154),(92095,1045,1357947905),(92112,1085,1355241583),(92181,1045,1357340812),(92181,1046,1357340809),(92209,1045,1357397829),(92209,1227,1357397828),(92311,1045,1358096495),(92317,1085,1355238708),(92328,1045,1358048665),(92427,1045,1355175111),(92439,1046,1357338907),(92484,1042,1357341225),(92484,1046,1357341377),(92541,1085,1355208783),(92657,1045,1355882466),(92657,1227,1355882465),(92697,1045,1357386617),(92735,1045,1355849539),(92760,1045,1356727432),(93067,1045,1357537707),(93300,1045,1357598854),(93529,1085,1355237312),(93625,1085,1355241929),(93627,1045,1355973381),(93707,1045,1357076013),(93755,1046,1357326759),(93797,1045,1357075292),(93878,1045,1357264165),(93934,1085,1355276405),(94018,1085,1355253550),(94137,1045,1357245075),(94145,1045,1358088378),(94159,1045,1357851502),(94159,15087,1357842645),(94159,15091,1357850804),(94161,1085,1355195891),(94222,1045,1355201882),(94229,1085,1355273003),(94281,1045,1357607219),(94321,1045,1357966859),(94359,1045,1357254918),(94414,1045,1356120348),(94429,1045,1357791096),(94500,1045,1357984696),(94500,1046,1357984601),(94572,1045,1357253566),(94626,1046,1357023885),(94804,1045,1357359669),(95085,1045,1357709563),(95085,1085,1355279942),(95772,1045,1358123722),(96272,15095,1356729725),(96394,1045,1357437451),(96519,1045,1357946706),(96679,1046,1357339943),(96722,1045,1357976597),(96744,1085,1355258714),(96748,1045,1355846328),(96790,1085,1355242823),(97093,1085,1355348043),(97175,1045,1357334125),(97255,1045,1357349700),(97431,1045,1357938295),(97860,1045,1357080786),(98312,1046,1357338968),(98367,1045,1357704017),(98441,1045,1357131756),(98649,1045,1357327869),(98670,1045,1357640999),(98670,1046,1357641061),(98984,1045,1357312336),(99284,1045,1357502091),(99456,1045,1357664593),(99895,1085,1355177522),(99907,1045,1357248548),(99921,1046,1357338325),(100006,1045,1357663646),(100073,15097,1357349697),(100643,1046,1357326987),(100644,1045,1357327698),(100899,1045,1355513679),(100929,1085,1355244099),(100950,1046,1357337986),(101179,1046,1357326925),(101205,1045,1357358738),(101249,851,1356036782),(101697,1045,1357938265),(101799,1045,1357089975),(101929,1045,1357944502),(102066,1046,1357324104),(103560,1046,1357326899),(103676,1045,1357365278),(103676,1236,1357235680),(103731,1045,1357945898),(103731,1046,1357337027),(103780,1045,1357261449),(103827,1045,1357075698),(103871,1045,1357080410),(103976,1045,1357327251),(104060,1045,1356126474),(104262,1045,1355509556),(104262,1085,1355259173),(104286,1045,1355366866),(104286,1227,1355366866),(104437,1045,1357400834),(104437,1227,1357400833),(104440,1045,1358003630),(104475,1046,1357336648),(104695,1046,1356490615),(104714,1045,1357763473),(104852,1045,1357180728),(105009,1085,1355261359),(105174,1045,1357374201),(105434,1045,1357931841),(105434,1085,1355234805),(105477,1045,1356149974),(105500,1085,1355241535),(105538,1046,1357337253),(105599,1045,1357128144),(105599,1046,1357340265),(105622,1045,1357999624),(105652,1045,1357935432),(105732,1085,1355239355),(105762,1045,1358023463),(105799,1045,1355848790),(105922,1045,1357327887),(105924,1045,1357598333),(105969,1046,1355445453),(105983,1045,1357327960),(106155,1045,1356126442),(106232,1085,1355271240),(106483,1045,1356120555),(106698,1085,1355252463),(106751,1085,1355248836),(107103,1045,1357401659),(107252,1045,1357959302),(107261,1085,1355238833),(107333,1045,1357076486),(107358,1045,1357358334),(107378,1085,1355287498),(107386,1046,1357336441),(107482,1045,1357896299),(107555,1045,1357358916),(107636,1046,1357339772),(107649,1085,1355235486),(107672,1046,1357254432),(107717,1046,1356717988),(107941,1085,1355247930),(107964,1045,1355515618),(108021,1085,1355238551),(108044,1045,1355178532),(108070,1045,1357371512),(108070,1085,1355248822),(108157,1045,1357658195),(108201,1045,1357358847),(108337,1045,1357789170),(108380,1045,1357348615),(108387,1085,1355285918),(108443,1046,1357324157),(108446,1045,1357698062),(108478,1045,1357970328),(108570,1046,1356596046),(108599,1045,1357090382),(108603,1045,1355510312),(108620,1045,1357960241),(108685,1045,1357693245),(108811,1085,1355269094),(108851,1045,1357362048),(108897,1085,1355242977),(109000,15056,1355239536),(109240,1045,1357250947),(109307,1045,1355518401),(109320,1045,1356618574),(109332,1045,1357251508),(109332,1227,1357251506),(109377,1046,1357249343),(109420,1046,1357244254),(109420,1085,1355237126),(109436,1045,1357954338),(109442,1045,1357934171),(109475,1085,1355239290),(109595,1045,1357327687),(109595,1227,1357327686),(109794,1085,1355240208),(109809,1045,1357077027),(109879,1045,1357358173),(110122,1045,1357335463),(110316,1046,1357326911),(110369,1045,1355820752),(110390,1085,1355176470),(110500,1045,1357088578),(110557,1045,1357359728),(111153,1045,1357109811),(111701,1236,1357264457),(111901,1045,1355842942),(111911,1045,1357353501),(112108,1046,1357341499),(112265,1085,1355275848),(112293,1045,1357353034),(112887,1045,1355543245),(113114,1045,1357934413),(113428,1046,1357338754),(113996,1085,1355245176),(114022,1085,1355240494),(114042,1045,1358037495),(114213,1085,1355450604),(114558,1046,1355862014),(114561,1085,1355255732),(114650,1085,1355237644),(114722,1085,1355236726),(114989,1045,1357347660),(115402,1045,1358130161),(115472,1045,1357363889),(115535,1045,1356218517),(115599,1045,1357939316),(115633,1045,1357661972),(115862,1045,1357347842),(115884,1046,1357339998),(115909,1045,1356126442),(116112,1046,1357324104),(116113,1085,1355276076),(116176,1045,1357347525),(116206,1046,1357337128),(116206,1085,1355261085),(116275,1045,1357340903),(116275,1046,1357340888),(116308,1045,1357246052),(116328,1046,1357338971),(116328,1085,1355504860),(116454,1046,1355469732),(116516,1045,1355178686),(116516,1227,1355178684),(116667,1085,1355250618),(116749,1046,1357727030),(116847,1045,1357485968),(116915,1045,1357965851),(116915,1085,1355241247),(116960,1045,1358018433),(117074,1045,1358034159),(117226,1045,1355237842),(117226,1085,1355351946),(117270,1085,1355262372),(117272,1045,1355931587),(117443,1045,1355518110),(117443,1046,1357341250),(117469,1236,1355527566),(117518,1045,1355531728),(117592,1046,1355643194),(117624,1045,1357304042),(117700,1085,1355245437),(117717,1045,1357585789),(117739,1046,1357336710),(117739,1085,1355253805),(117804,1085,1355249794),(117814,1046,1357339732),(117932,14,1356313184),(117939,1045,1357248329),(117975,1045,1357345971),(118164,1085,1355206605),(118208,1045,1355511565),(118353,1045,1357179882),(118368,1045,1357933933),(118376,1045,1357598026),(118786,1085,1355257579),(118812,1236,1357934261),(118853,1045,1357935615),(118856,1045,1358028854),(118862,1046,1357337192),(118865,1046,1357339677),(118960,1045,1355181906),(119003,1045,1357763408),(119054,1085,1355249853),(119067,1045,1356189438),(119105,1045,1355506978),(119105,1085,1355235846),(119172,14,1357577170),(119220,1085,1355254372),(119440,1085,1355176526),(119456,1046,1357328946),(119558,1045,1357327876),(119558,1085,1355288838),(119665,1045,1355174788),(119681,1045,1357444301),(119715,1045,1355226397),(119821,1085,1355235826),(119864,1045,1357335536),(120192,1045,1357663212),(120192,1046,1357663390),(120263,1045,1357945222),(120328,1045,1357014360),(120408,1046,1357263045),(120408,1085,1355365275),(120411,1045,1358006025),(120418,1045,1357251407),(120502,1045,1356119607),(120533,1085,1355433062),(120729,1045,1358032360),(120831,1045,1357358122),(120840,11945,1357421431),(120887,1045,1355823911),(120893,1085,1355241411),(120926,1085,1355244259),(120933,1045,1357366371),(120986,1045,1358007412),(120992,1046,1357337566),(121013,1085,1355240693),(121238,1045,1357277078),(121238,1085,1355284402),(121332,1045,1355223373),(121340,1045,1357813057),(121412,1045,1358089307),(121441,1085,1355331525),(121611,1045,1357912804),(121611,1046,1357912545),(121821,1045,1357955312),(121821,1236,1357348735),(124535,1046,1357337177),(125335,1045,1357576199),(127609,1085,1355247739),(128963,1045,1357582918),(129520,1046,1357328886),(129536,1045,1357826106),(130426,1045,1356199712),(130776,1045,1357944490),(131540,1045,1357311013),(132948,1045,1357335587),(138356,1045,1358055874),(138384,1046,1357340930),(140571,1045,1357325976),(140852,1236,1357327531),(141716,1045,1356822130),(143358,1085,1355251320),(144171,1046,1358065440),(146887,1236,1355773297),(147393,1045,1357327288),(147959,1046,1357326863),(148934,1045,1355197688),(149254,1046,1357861468),(150382,1045,1357843074),(151677,1046,1355502725),(151677,1085,1355250409),(152224,1046,1356718675),(152406,1045,1355543223),(157491,1085,1355243069),(158624,1045,1357249036),(160742,1045,1356402423),(160742,1046,1357326869),(161077,1045,1357956223),(162536,1085,1355325535),(164371,1045,1358099362),(165072,1045,1357364943),(167776,1045,1358048225),(167776,1046,1355675188),(168422,1045,1357837623),(173276,1045,1357353940),(173349,1085,1355238859),(174473,1045,1357947405),(178824,1045,1356568956),(179581,1045,1358005092),(180154,1045,1357959875),(180154,1046,1357254300),(180241,1045,1355524534),(180429,1085,1355257224),(181608,1085,1355237302),(191991,1045,1357328042),(191991,1236,1357323359),(193707,1045,1357327916),(193707,1046,1356363176),(197056,1045,1355808018),(197998,1085,1355242339),(201178,1046,1355822300),(202156,1045,1357348360),(202510,1045,1357930431),(202510,1046,1357930717),(202510,11820,1357830362),(202510,11838,1357576998),(202510,11844,1357577078),(202510,11922,1357830745),(202510,11927,1357830739),(202510,11941,1357830741),(202510,11942,1357830747),(202510,11943,1357830750),(202510,11944,1357830757),(202510,12071,1357830752),(202510,12099,1357830755),(202510,12203,1357830743),(202510,12267,1357830737),(202510,12525,1355495941),(202510,14583,1355495959),(202510,14812,1355495961),(202510,14824,1355495591),(202510,14836,1355495567),(202510,14971,1355495531),(202510,15059,1355251532),(202510,15066,1355488587),(202510,15068,1355488718),(202510,15069,1355423078),(202510,15070,1355488712),(202510,15071,1355489848),(202510,15072,1355493618),(202510,15077,1355854574),(202510,15078,1355848986),(202510,15080,1355936526),(202510,15083,1355936357),(202510,15085,1356098016),(202510,15087,1356103930),(202510,15088,1356106482),(202510,15090,1357316938),(202510,15094,1357137075),(202510,15095,1357316988),(202510,15097,1357311951),(202510,15100,1357577365),(202510,15104,1357913256),(202510,15105,1357913254),(202510,15106,1357849914),(202510,15107,1357913249),(202510,15108,1357912992),(202510,15109,1357830901),(202510,15110,1357913244),(202510,15114,1357918242),(204834,1085,1355278283),(207074,1045,1357767425),(208630,1236,1357828461),(219503,1046,1355807516),(220941,1045,1357625319),(224918,1045,1358034344),(226479,1045,1357347642),(227737,1046,1357708115),(230668,1045,1357965396),(233341,1046,1357339861),(237398,1046,1357341179),(238948,1045,1357987761),(238948,1227,1357987760),(239627,1045,1357891831),(239772,1046,1357341118),(241170,1045,1358104727),(243090,1085,1355240441),(244092,1085,1355254613),(244108,1045,1357957012),(247328,1045,1357344742),(250808,1045,1357406034),(251560,1046,1357340059),(259616,1046,1357336140),(259658,1045,1358030601),(259668,1046,1357341195),(260011,1045,1357936174),(260011,1085,1355247020),(260011,1227,1357935976),(260017,1045,1357264425),(260017,1227,1357264424),(260022,1046,1357341508),(260022,1085,1355270793),(260553,1045,1357954491),(260573,1236,1357497436),(260587,1046,1357258273),(260611,1085,1355288927),(261402,1046,1357336864),(261457,1045,1358132681),(261644,1085,1355236650),(261660,1045,1358003922),(261795,1046,1357341461),(261921,1045,1357940833),(261992,1085,1355331459),(262035,15070,1355658712),(262269,1045,1358003562),(262580,1045,1357358687),(262601,1085,1355236412),(262609,1045,1357670060),(262621,1046,1357326734),(262640,1046,1355927461),(262658,1046,1357338720),(262661,1045,1357398380),(262689,1046,1357339302),(262731,1045,1357347806),(262924,1085,1355245634),(263226,1045,1357081948),(263227,1045,1358119398),(263227,1046,1356620044),(263306,1045,1357985382),(263428,1045,1358045108),(263551,15051,1355833857),(263671,1045,1357352909),(263673,1045,1357936660),(263820,1045,1357938231),(263941,1236,1357076893),(264039,1045,1355264627),(264039,1085,1355264733),(264043,1045,1357327919),(264113,1085,1355236250),(264139,1045,1357517494),(264156,1046,1356964686),(264160,1046,1357260446),(264349,1045,1357327732),(264426,1236,1357073766),(264432,1236,1357329500),(264554,1085,1355275221),(264566,1085,1355179803),(264616,1045,1357947546),(264616,1085,1355246447),(264631,1046,1357587785),(264737,1085,1355250961),(264746,1046,1357326913),(264893,1045,1357953692),(264893,1046,1357339090),(264949,1045,1357328096),(265167,1045,1357933157),(265253,1045,1357139014),(265268,1045,1357685426),(265342,1046,1357336988),(265404,1045,1355191039),(266873,1085,1355238047),(266900,1045,1357349817),(266927,1085,1355244715),(267094,1046,1357336406),(267410,1085,1355198294),(267504,1045,1357889970),(267504,1046,1357889699),(267851,1045,1355791399),(267851,1046,1355791364),(268032,1045,1357932945),(268032,1046,1357324118),(268053,1046,1357339443),(268081,1045,1357246333),(268097,1045,1357414730),(268156,1046,1357337403),(268289,1046,1357338353),(268352,1046,1357008930),(268500,1045,1357303293),(268513,1045,1357256437),(268523,1045,1356141006),(268537,1045,1355552118),(268537,1046,1357625659),(268887,1236,1357438317),(268946,1045,1357948686),(268979,1046,1357338202),(268979,1085,1355249284),(269044,1046,1357947051),(269052,1085,1355239475),(269284,1046,1356322678),(269475,1045,1357951552),(269638,1045,1357932673),(269741,1045,1357642357),(269773,1046,1357246922),(269841,1045,1357346835),(269862,1046,1358066346),(269886,1046,1357341215),(270006,1046,1356378198),(270025,1085,1355274848),(270046,1045,1357952599),(270046,1046,1357338602),(270063,1085,1355310371),(270096,1045,1356981931),(270164,1045,1357246532),(270203,1085,1355273565),(270260,1085,1355242655),(270329,1085,1355268389),(270381,1085,1355280126),(270622,1045,1357616800),(270624,1045,1358052937),(270810,1046,1357339730),(270940,1085,1355242439),(270968,1045,1357950396),(271033,1045,1357688123),(271140,1085,1355237212),(271366,1085,1355280424),(271423,1085,1355288937),(271470,1045,1357352695),(271479,1085,1355321729),(271554,1045,1357256571),(271569,1045,1355855996),(271583,1046,1357324763),(271591,1085,1355237456),(271822,1045,1355537104),(271822,1046,1357254427),(271877,1045,1357273546),(271947,1045,1357330761),(271975,1045,1357933631),(272014,1045,1357949279),(272042,1045,1356125747),(272089,1085,1355316533),(272116,1085,1355237566),(272191,1046,1357208444),(272219,1045,1357077449),(272346,1045,1357947090),(272431,1085,1355263211),(272443,1085,1355250874),(272586,1085,1355253133),(272715,1045,1357997434),(272765,1085,1355330308),(273001,1085,1355241189),(273016,1085,1355257280),(273020,1085,1355248858),(273035,1045,1357775944),(273035,1085,1355265834),(273088,1085,1355245426),(273285,1236,1357328678),(273329,1045,1357244556),(273416,1085,1355244797),(273463,1046,1357934198),(273501,1046,1357339307),(273502,1046,1357336086),(273567,1085,1355400973),(273727,1045,1357938563),(273751,1045,1357087694),(273827,1045,1357351070),(273857,1045,1357352407),(273900,1045,1357433719),(273900,1046,1356455486),(274068,1045,1358008780),(274137,1236,1357074061),(274153,1040,1357340606),(274153,1042,1357340577),(274153,1045,1357340607),(274153,1046,1357340578),(274196,1045,1357619580),(274196,1046,1357619575),(274208,1045,1357959461),(274230,1045,1357336813),(274250,1046,1357337155),(274366,1045,1358014301),(274548,1046,1357675026),(274624,1046,1357327904),(274661,1045,1358023593),(274710,1045,1357936132),(274710,1236,1357331751),(274713,1045,1358013440),(274721,1045,1355510999),(274721,1046,1357336104),(274731,1085,1355260942),(274741,1045,1357286498),(274754,1046,1357336985),(274769,1085,1355260663),(274794,1085,1355247478),(274815,1045,1357936454),(274818,1045,1356489488),(274851,1045,1357611242),(274863,1085,1355259727),(274983,1045,1357582031),(274983,1236,1357581533),(275075,1046,1357339579),(275198,1045,1358164142),(275346,1045,1358125779),(275410,1045,1357325272),(275470,1045,1357950162),(275499,1046,1357338049),(275741,1045,1357932888),(275741,1085,1355371987),(275752,1045,1358104481),(275915,1085,1355251086),(276015,1045,1357932447),(276080,1045,1357149062),(276080,7628,1357149323),(276206,1045,1357854422),(276276,1085,1355243984),(276284,1045,1357584421),(276300,1045,1357250507),(276337,1045,1355530838),(276357,1045,1358091439),(276402,1085,1355240407),(276537,1045,1356122714),(276537,1085,1355238269),(276632,1085,1355235079),(276786,1046,1357326769),(276991,1045,1357599091),(277225,1045,1357950967),(277441,1085,1355250152),(277776,1040,1357934070),(277776,1042,1357933829),(277776,1045,1357934073),(277879,1045,1357348264),(279023,1045,1356134460),(279040,1045,1358027009),(279137,1045,1357358395),(279290,1046,1357336545),(279349,1045,1355524326),(279415,1085,1355257372),(279461,1046,1357341054),(279549,1045,1357314987),(279549,1046,1357339517),(279660,1045,1357589021),(279772,1045,1355289456),(279924,1045,1358052976),(279938,1045,1357140555),(279938,1046,1356464558),(279938,1227,1357140554),(279938,1236,1357680104),(280049,1045,1357946652),(280224,1046,1357340563),(280266,1042,1357341396),(280266,1046,1357341527),(280439,1046,1357338700),(280461,1046,1355917340),(280479,1085,1355239096),(280533,1046,1357337476),(280572,1045,1357663866),(280661,1045,1358023751),(280668,1085,1355256401),(280827,1045,1356203966),(280827,1085,1355257010),(280833,1085,1355268872),(280864,1085,1355240226),(281032,1046,1357336768),(281064,1085,1355259159),(281174,1085,1355242328),(281207,1045,1357939209),(281207,1085,1355280751),(281214,1045,1357259907),(281239,1039,1357330409),(281239,1046,1357330409),(281263,1046,1357339986),(281461,1046,1357329000),(281461,1236,1357329071),(281466,1085,1355235960),(281481,1046,1357338135),(281483,1046,1355309343),(281578,1045,1357075939),(281607,1046,1357340525),(281636,1085,1355251463),(281842,1085,1355243550),(281921,1045,1357081417),(282023,1085,1355277136),(282052,1085,1355235078),(282056,1045,1357347333),(282068,1046,1357339776),(282068,1085,1355361925),(282095,1045,1357348073),(282112,1045,1358028313),(282161,1085,1355265660),(282301,1045,1357091251),(282352,1046,1357338321),(282352,1085,1355288283),(282357,1045,1357676537),(282443,1085,1355237923),(282454,1045,1357445763),(282454,1085,1355254329),(282464,1085,1355294640),(282481,1045,1357249962),(282492,1236,1357324059),(282536,1045,1357931774),(282667,1045,1357947744),(282700,1045,1355923747),(282841,1040,1357147292),(282841,1045,1357147293),(282851,1085,1355247817),(283084,1045,1357945054),(283180,1085,1355237772),(283384,1085,1355293153),(283388,1045,1357294087),(283447,1045,1355629526),(283447,1227,1355629524),(283447,1236,1355629491),(283494,1045,1357698559),(283497,1045,1355252621),(283518,1045,1357934335),(283529,1046,1357323669),(283575,1045,1357677928),(283606,1045,1357944173),(283606,1227,1355689210),(283649,1045,1358094747),(283649,1046,1358094740),(283845,1045,1357355315),(284023,1046,1357337523),(284184,1045,1357927796),(284370,1045,1357398679),(284391,1045,1355811289),(284611,1046,1357326883),(284722,1045,1357940857),(284757,1045,1355809915),(284832,1045,1357663830),(284925,1045,1357130582),(285054,1045,1357253439),(285054,1046,1357337695),(285060,1045,1355512634),(285123,1045,1357249896),(285136,1045,1356377196),(285374,1045,1357352937),(285377,1045,1357932609),(285377,1046,1356488092),(285388,1045,1357358421),(285403,1085,1355242524),(285514,1045,1357933712),(285514,1046,1357934165),(285585,1045,1357949148),(285611,1045,1357312012),(285767,1045,1355854208),(285886,1045,1358039790),(285917,1236,1357180289),(285928,1085,1355272233),(286027,1045,1355193026),(286031,1045,1357347022),(286095,1045,1358139071),(286226,1045,1357952117),(286259,1085,1355249853),(286347,1045,1357477745),(286347,1046,1356527360),(286433,1045,1357839088),(286559,1045,1356131034),(286665,1045,1357346669),(286951,1045,1357139763),(286983,1085,1355249833),(287017,1236,1355938985),(287021,1046,1357338762),(287021,1236,1356572507),(287080,1045,1356565567),(287118,1045,1357765688),(287253,1085,1355254840),(287409,1085,1355241935),(287517,1045,1357934242),(287619,1045,1358122313),(287621,1045,1357335549),(287668,1085,1355236720),(287809,1045,1358117834),(287809,1227,1358117832),(287927,1046,1357337546),(288126,1045,1357942135),(288182,1045,1355274635),(288272,1046,1357267635),(288273,1045,1357947941),(288333,1040,1357075961),(288333,1045,1357075889),(288351,1085,1355277611),(288561,1045,1355806023),(288652,1085,1355253864),(288837,1085,1355241052),(289009,1085,1355183525),(289056,1046,1357336955),(289148,1046,1357360158),(289569,1085,1355250631),(289889,1085,1355290173),(290106,1045,1355855034),(290108,1085,1355279962),(290116,1045,1357246125),(290123,1045,1357332861),(290123,1046,1356007812),(290189,1045,1356173159),(290189,1085,1355315765),(290215,1085,1355236512),(290228,1046,1356088159),(290239,1045,1358158824),(290505,1085,1355237804),(290611,1085,1355279638),(290740,1045,1358040456),(290811,1046,1357340698),(291038,1045,1357933879),(291158,1045,1357148540),(291441,1045,1357658080),(291579,1045,1358005701),(291798,1045,1358052201),(291844,1045,1357663479),(291873,1045,1355264722),(292210,1236,1357407544),(292376,1045,1357150039),(292404,1085,1355237559),(292486,1046,1357743614),(292524,1045,1357248980),(292709,1045,1357255586),(292742,1045,1358006450),(292743,1085,1355240609),(292754,1045,1357245653),(292939,1085,1355272742),(292971,1085,1355419377),(293020,1045,1358016387),(293074,1085,1355248928),(293370,1045,1357075065),(293800,1046,1357340541),(293908,1045,1358047208),(293983,1045,1355509523),(294205,1046,1357606780),(294256,1046,1357338303),(294256,1085,1355235968),(294467,1045,1355883858),(294495,1040,1357937940),(294495,1045,1357937942),(294495,1085,1355246618),(294959,1045,1357978240),(295448,1085,1355241350),(295686,1045,1357942245),(295758,1045,1357327828),(295866,1085,1355249935),(295994,1045,1357935540),(296053,1045,1357244611),(296464,1046,1357479958),(296474,1046,1357340709),(296474,1085,1355267577),(296625,1046,1357341361),(296718,1045,1357689099),(296794,1045,1355511807),(297060,1085,1355272900),(297277,1045,1357942990),(297277,1046,1357340975),(297372,1042,1357337898),(297372,1046,1357337952),(297392,1085,1355235717),(297420,1045,1358023501),(297420,1085,1355263838),(297543,1045,1357347870),(297699,1045,1357970409),(298007,1045,1357322146),(298154,1045,1357673012),(298216,1045,1355247039),(298237,1046,1357259236),(298272,1046,1355761688),(298276,1045,1356144877),(298455,1045,1357406395),(298563,1045,1357405827),(298790,1045,1355860902),(298846,1085,1355250814),(298882,1045,1357398182),(298915,1045,1357358651),(298915,1046,1357358583),(299027,1046,1357337109),(299080,1045,1355932633),(299208,1085,1355251975),(299435,1236,1357508674),(299528,1046,1357726083),(299562,1040,1357337405),(299562,1045,1357337406),(299562,1046,1357337509),(299671,1045,1355514250),(299842,1042,1357663671),(299842,1045,1357663672),(299842,1046,1357663620),(299993,1045,1358097605),(300030,1045,1357779286),(300249,1045,1358097660),(300308,1045,1357956552),(300419,1045,1357369688),(300515,1045,1358011223),(300575,1045,1356136686),(300976,1085,1355269729),(301114,1045,1355888657),(301114,1085,1355236067),(301258,1046,1357337277),(301280,1085,1355248146),(301466,1045,1357340841),(301655,1045,1358001407),(301679,1045,1357948072),(301753,1045,1357335071),(301861,1045,1357921591),(301920,1045,1357391840),(301944,1045,1357874870),(302031,1045,1355508872),(302570,1046,1357467914),(302741,1040,1357663866),(302741,1042,1357663852),(302741,1045,1357664035),(303740,1085,1355289732),(303931,1045,1356121244),(304035,1045,1355509371),(304178,1045,1357327518),(304260,1085,1355245914),(304473,1046,1357336242),(304586,1046,1357326873),(304628,1085,1355329976),(305063,1085,1355239081),(305135,1045,1357358758),(305136,1045,1358049582),(305296,1085,1355240029),(305538,1045,1357607217),(305554,1045,1358009628),(305610,1046,1356833474),(305983,1046,1357861490),(306056,1045,1357966906),(306131,15094,1357258190),(306166,1045,1357966690),(306339,1045,1357331717),(306543,1045,1356740641),(306558,1045,1357075787),(306580,1045,1357591764),(306635,1045,1358021205),(306864,1045,1357365638),(307014,1085,1355276531),(307065,1045,1357601573),(307621,1045,1357413019),(307621,1085,1355243056),(307633,1045,1357940061),(307715,1046,1357340874),(307726,1085,1355317182),(308109,1085,1355236394),(308301,1045,1357380211),(308301,1046,1357720667),(308301,1236,1357380222),(308570,1045,1356987236),(308575,1045,1357245542),(308585,1045,1357327918),(308662,1045,1357370424),(309161,1045,1358101976),(309189,1045,1355512667),(309195,1045,1355177258),(309366,1085,1355268322),(309369,1045,1357951410),(309495,1045,1355225804),(309554,1045,1357949354),(309882,1046,1357339733),(309974,1045,1357953082),(310028,1045,1357335609),(310728,1046,1357323640),(310737,1045,1357964420),(310783,1085,1355236746),(310928,1046,1356497522),(311074,1045,1357327738),(311383,1045,1357309815),(311503,1045,1357076030),(311726,1045,1355845394),(312030,1045,1357266063),(312030,1227,1357266062),(313061,1045,1356569678),(313061,1227,1356569676),(313345,1045,1357934052),(313677,1045,1355585699),(313795,1085,1355280359),(313999,1045,1357335528),(314004,1040,1357337064),(314004,1042,1357337306),(314004,1045,1357337065),(314004,1046,1357337308),(314076,1045,1356122679),(314210,1045,1357365168),(314210,1085,1355237276),(314232,1045,1357962897),(314237,1045,1357338273),(314237,1046,1357338328),(315608,1045,1357353484),(315624,1085,1355246999),(315731,1085,1355242469),(315921,1085,1355250404),(316110,1085,1355256267),(316149,1085,1355237380),(316164,1045,1357250481),(316328,1046,1355389418),(316417,1045,1355523858),(316449,1046,1357338818),(316613,1085,1355267201),(317073,1045,1357957237),(317073,1085,1355242117),(317567,1045,1357588410),(317931,1085,1355238773),(318593,1046,1357338372),(318693,1045,1357945987),(318693,1046,1357335938),(319093,1236,1357246937),(319260,1045,1357369061),(319338,1085,1355236674),(319385,1085,1355279039),(319475,1236,1355182537),(319526,1045,1357840515),(319646,1085,1355238404),(319839,1045,1357352538),(319984,1045,1357760981),(320672,1046,1357324104),(320983,1045,1357365520),(321209,1045,1357956769),(321374,1236,1358113014),(321431,1046,1357337551),(321578,1045,1357348151),(322018,1046,1357341024),(322038,1045,1357932190),(322056,1045,1358053723),(322160,1085,1355237232),(322198,1085,1355271564),(322205,1045,1357935886),(322746,1046,1357340432),(322746,1085,1355267321),(322831,1045,1356574965),(322831,1236,1356574988),(322877,1236,1357157551),(322894,1045,1357253453),(322999,1236,1357227358),(323228,1085,1355235967),(323494,1236,1355209237),(323588,1045,1357822618),(323671,1045,1357359484),(323754,1236,1355175596),(323810,1045,1355812568),(323849,1085,1355311114),(324272,1046,1357249332),(324425,1045,1355190908),(324425,1227,1355190903),(325069,1045,1357737293),(325352,1227,1357100811),(325482,1045,1358161401),(325755,1045,1357075432),(325816,1236,1357438831),(325949,1045,1355511151),(326096,1045,1357944545),(326206,1085,1355236710),(326327,1045,1357369213),(326327,1046,1357369135),(326504,1085,1355239214),(326764,1045,1357341898),(327068,1085,1355258411),(327222,1045,1357089430),(327222,1046,1357340327),(327240,1045,1356738796),(327240,1227,1356738795),(327278,1045,1357377806),(327649,1045,1356026418),(327980,1045,1358112539),(328030,1085,1355239498),(328037,1085,1355242420),(328128,1046,1357802704),(328459,1085,1355277969),(328565,1085,1355235984),(328761,1085,1355238578),(328767,1045,1357081845),(328777,1045,1357933922),(328910,1236,1355253824),(328963,1046,1357339870),(328982,1045,1357365744),(329363,1045,1357322141),(329552,1236,1357397543),(329593,1045,1357355162),(329611,1046,1357336625),(330824,1085,1355252581),(331138,1085,1355244408),(331710,1045,1357358696),(331710,1085,1355243670),(331874,1045,1357620465),(331903,1045,1357244716),(331918,1045,1357357853),(332148,1045,1357328028),(333011,1045,1357251729),(333016,1045,1357931952),(333272,1085,1355274499),(333507,1045,1357251010),(333581,1045,1355811342),(333845,1045,1356136842),(334064,1085,1355291308),(334238,1046,1357673407),(334268,1046,1357328367),(334292,1045,1355936731),(334292,1227,1355936729),(334386,1085,1355237292),(334454,1045,1357949440),(334454,1046,1356408204),(334728,1045,1357335585),(334956,1045,1357321251),(334964,1046,1357324103),(335311,1085,1355243793),(335521,1085,1355239651),(335746,1085,1355241382),(335979,1085,1355257940),(336136,1046,1356802413),(336443,1045,1358018285),(336813,1045,1357258766),(336945,1085,1355248279),(337181,1045,1358114596),(337181,1227,1358114610),(337223,1085,1355261545),(337268,1085,1355244254),(337520,1045,1358097737),(337527,1236,1357852806),(337555,1045,1355834215),(337732,1085,1355275939),(337814,1085,1355252815),(338032,1085,1355239846),(338226,1045,1355536271),(338699,1236,1357941951),(338775,1045,1357359528),(338994,1046,1357341083),(339007,1045,1355816303),(339007,1227,1355816302),(339077,1046,1357337634),(339077,1085,1355246075),(339217,1045,1356127710),(339217,1085,1355366767),(339779,1046,1355494354),(339830,1045,1357992696),(339830,1046,1357817404),(339928,1085,1355447569),(339968,1236,1357945151),(340024,1045,1358026496),(340239,1045,1355507232),(340257,1085,1355243870),(340300,1085,1355333820),(340392,1085,1355270896),(340423,1085,1355284438),(340785,1045,1357934475),(340870,1045,1356128381),(340973,1045,1357254420),(340979,1046,1356797311),(341014,1045,1357961789),(341268,1045,1357324484),(341445,1085,1355284989),(341567,1045,1357939552),(341603,1085,1355236235),(341746,1045,1355184977),(341800,1045,1357358325),(341815,1045,1357359645),(342911,1046,1357326886),(343053,1045,1357939732),(343093,1045,1357590648),(343262,1046,1357337995),(343476,1045,1357933726),(343659,1045,1357309026),(343784,1045,1357992201),(343840,1045,1357611479),(343908,1045,1357077613),(343996,1045,1355512534),(344002,851,1356042327),(344512,1045,1357617806),(344554,1045,1355512657),(344609,1045,1357320126),(344683,1045,1357368103),(344934,1046,1356503023),(344999,1045,1357935738),(345195,1045,1357078090),(345404,1046,1357205723),(345985,1045,1357347481),(345996,1045,1357342680),(346180,1046,1358104588),(346186,1045,1357091790),(346339,1046,1357868801),(346597,1045,1357613556),(346873,1045,1356661843),(346873,1046,1356509261),(346882,1045,1357359146),(346901,1045,1357278511),(346906,1045,1357266881),(346964,1046,1357089974),(347073,15094,1357482660),(347073,15097,1357301822),(347299,1085,1355267539),(347304,1045,1355186414),(347310,1046,1356390137),(347675,1045,1356126595),(347842,12081,1356539047),(348815,1045,1357228054),(348923,1236,1356056657),(349091,1045,1357931202),(350014,1045,1357078647),(350442,1045,1358011038),(350650,1085,1355235847),(350773,1045,1357605526),(350811,1046,1357336415),(350880,1085,1355239809),(350996,1236,1357423821),(351033,1236,1357094611),(351080,1046,1357324054),(351100,11945,1357101556),(351138,1045,1357361716),(352063,1045,1357933676),(352643,1045,1357914311),(352731,1045,1355810296),(352736,1046,1355576256),(352959,1045,1357769245),(353223,1045,1355731451),(353940,1046,1357339736),(354024,1045,1357249331),(354523,1045,1357655006),(354830,1045,1357955126),(354836,1045,1357417109),(354836,1046,1357341331),(354836,1085,1355268836),(354967,1085,1355238183),(355102,1045,1355872833),(355123,1085,1355255021),(355132,1045,1357081808),(355675,1085,1355273379),(355958,1045,1357245021),(355987,1045,1356121296),(356071,1045,1355179127),(356125,1085,1355236295),(356313,1045,1355505214),(356961,1045,1355837213),(357090,1085,1355241952),(357136,1085,1355240951),(357224,1040,1355849534),(357224,1045,1355849536),(357224,1046,1355849509),(357276,1236,1357246890),(357386,1045,1357494158),(357520,1085,1355268595),(357587,1085,1355247410),(357609,1046,1357337825),(357684,1085,1355258639),(357710,1085,1355256043),(358120,1085,1355302836),(358259,1045,1355813289),(358339,1236,1357328951),(358540,1045,1357081041),(358605,1085,1355239195),(359011,1045,1357334186),(359200,1045,1357328083),(359263,1046,1357337705),(359263,1085,1355242965),(359268,1046,1357326919),(359343,1045,1357227043),(359511,15074,1355636081),(359565,1045,1355507251),(359572,1045,1357307259),(359576,1045,1357383895),(359578,1085,1355237734),(359739,1045,1358036073),(359834,1045,1355841303),(359834,1227,1355841303),(359920,1045,1357100177),(359973,1045,1357365306),(359973,1236,1357250273),(359973,11945,1357249399),(360984,1046,1356793294),(361069,1045,1357347511),(361187,1085,1355237980),(361224,1045,1357359381),(361261,1045,1357948825),(361287,1046,1357340305),(361293,1085,1355356063),(361345,1085,1355257630),(361469,1085,1355359634),(361481,1045,1356126916),(361481,1085,1355264558),(361516,1045,1355555289),(361533,1045,1356976751),(361888,1045,1358082730),(362189,1046,1357339996),(362260,1045,1357078342),(362261,1045,1357345846),(362414,1085,1355264090),(362543,1045,1358001374),(362801,1045,1355743007),(363370,1045,1358110680),(363490,1045,1357401226),(363832,1045,1357338231),(363832,1046,1357338230),(363928,1045,1358005210),(364009,1045,1358051055),(364141,1046,1357341066),(364150,1045,1358019915),(364258,1085,1355236379),(364341,1045,1357335590),(364397,1045,1357679064),(364397,1227,1357679062),(364594,1045,1355196121),(365067,1045,1357346326),(365067,1046,1355698152),(365613,1045,1357073847),(365613,1227,1357073843),(365882,1045,1355847616),(365882,1085,1355241216),(365882,1227,1355847614),(366188,1085,1355234981),(366385,1046,1356809198),(366499,1045,1357603310),(366549,1045,1358117752),(366549,1046,1357869378),(366623,1046,1357340932),(366656,1045,1357277760),(366756,1045,1355828376),(366864,1046,1357340278),(366887,1045,1357076104),(366887,1227,1357076103),(367117,1046,1357340212),(367144,1045,1357374296),(367144,1046,1357807417),(367149,1046,1357336670),(367221,1046,1356486457),(367462,1085,1355241115),(367560,1045,1357775689),(367893,1046,1355382840),(368076,1045,1355954213),(368150,1045,1356985373),(368210,1045,1355890676),(368210,1085,1355239055),(368623,1045,1357312739),(368692,1046,1357760123),(369432,1045,1357327975),(369907,1045,1357328416),(369907,1227,1357328415),(370050,1085,1355240604),(370137,1045,1357252407),(370137,1236,1357252421),(370243,1045,1357944625),(370332,1085,1355236083),(370724,1045,1356972342),(371111,1046,1357336245),(371137,1045,1358011553),(371297,1045,1357578446),(371444,1236,1355187405),(371602,1045,1355834735),(371692,1045,1358002642),(371692,15069,1355587396),(371750,1085,1355239718),(371754,1085,1355238519),(371773,1045,1357352646),(371909,1046,1357723411),(371975,1045,1357954687),(372204,1045,1357272314),(372256,1085,1355193957),(372270,1045,1357348859),(372416,1045,1357256442),(372543,1085,1355247187),(372712,1046,1357340198),(372989,1045,1355176209),(373159,1045,1358106802),(373451,1045,1357933375),(373475,1045,1357245816),(373477,1085,1355275967),(373524,1045,1357244489),(373752,1085,1355235959),(373840,1045,1357360075),(373943,1045,1357229162),(374088,1045,1357665844),(374088,1227,1357665841),(374088,1236,1357665804),(374167,1045,1357355165),(374256,1040,1357338711),(374256,1042,1357338651),(374256,1045,1357338726),(374256,1046,1357339174),(374415,1045,1357335507),(374905,1046,1357336673),(374928,1045,1357317211),(375073,1045,1357353042),(375209,1045,1357690682),(375276,1045,1357319056),(376612,1046,1357339789),(376848,1045,1357075039),(376928,1045,1357628726),(377277,1085,1355243977),(377304,1045,1357810117),(377492,1045,1357328079),(377586,1046,1357339367),(377679,1046,1357336435),(377694,1085,1355260892),(377814,1045,1357761547),(377849,1045,1355522106),(378019,1046,1357337665),(378074,1236,1357531456),(378214,1045,1357003924),(378244,1045,1357337175),(378244,1046,1357337519),(378653,1045,1357652266),(378680,1045,1358124920),(378751,1046,1357336656),(378772,1085,1355236840),(378772,1236,1355236861),(379119,1046,1357338447),(379127,1045,1356725114),(379127,1046,1357341029),(379176,1045,1357996702),(379176,1085,1355239908),(379182,1045,1357867586),(379200,1085,1355235615),(379356,1045,1357796296),(380185,1045,1357609643),(380243,1045,1357664780),(380503,1085,1355457693),(380974,1045,1357977514),(381111,1085,1355243669),(381246,1045,1357995999),(381262,1085,1355236674),(381406,1046,1357324100),(381469,1045,1358002330),(381731,1045,1357247941),(381790,1045,1357388517),(381924,1085,1355248301),(381935,1085,1355351200),(382017,1085,1355267316),(382207,1045,1357291368),(382496,1046,1357339525),(382733,1085,1355236626),(382957,1046,1357341517),(383181,1045,1357359112),(383489,1045,1357951071),(383671,1045,1357947436),(383747,1085,1355254206),(384594,1085,1355248488),(384825,1085,1355246340),(384890,1045,1355809914),(385142,1045,1355878319),(385394,1045,1355592274),(385394,1046,1357335322),(385416,1046,1357326909),(385526,1085,1355252952),(385608,1085,1355284446),(386170,1045,1355875321),(386170,1046,1357340164),(386467,1045,1355830934),(386801,1236,1355831977),(386870,1045,1356392296),(386870,1227,1356392295),(386917,1045,1357347512),(387021,1045,1355501080),(387495,1085,1355242242),(387684,1045,1358107626),(387684,1236,1358107597),(387727,1045,1357079353),(387929,1045,1357768429),(388006,1085,1355243453),(388023,1045,1357244858),(388049,1045,1357606220),(388215,1045,1357831797),(388215,1046,1357831819),(388215,1236,1357666997),(388215,15035,1355244595),(388215,15091,1356620005),(388550,1085,1355243565),(388733,1045,1356128459),(388763,1227,1357081000),(388817,1046,1357337827),(389356,1085,1355238741),(389815,1045,1357936413),(390277,1045,1356123893),(390326,1046,1358065760),(391466,1045,1357327693),(391900,1045,1357006688),(391997,1045,1357527377),(392473,1045,1356973651),(392473,1227,1356973649),(392473,1236,1356973642),(393326,1045,1357942003),(393577,1046,1357337870),(393590,1046,1357337756),(394637,1085,1355260082),(394653,1046,1356181514),(394809,1045,1355516015),(394865,1085,1355241295),(395007,1045,1355525615),(395007,1085,1355277977),(395017,1045,1357322301),(395174,1085,1355241414),(395300,1085,1355258662),(395300,1236,1356392002),(395514,1085,1355248236),(395739,1045,1355182834),(395739,1085,1355182854),(396084,1045,1357247658),(396088,1236,1357138250),(396334,1045,1357954950),(396345,1045,1355838378),(396345,1227,1355838377),(396419,1045,1357943755),(396419,1046,1357338394),(396636,1045,1356194763),(396982,1045,1358008379),(397031,1045,1355824172),(397113,1046,1357338996),(397186,1085,1355409726),(397208,1045,1357328566),(397213,1085,1355238166),(397334,1046,1357337776),(397350,1045,1357352709),(397418,1045,1355631882),(397467,1045,1357345242),(397587,1045,1357245119),(397695,1045,1357955839),(397848,1045,1355843218),(398399,1045,1357965542),(398470,1045,1357672561),(398519,1046,1357339523),(398727,1045,1357681690),(398752,1045,1357358127),(398871,1045,1357316240),(398940,1046,1357339145),(399561,1045,1357353404),(399992,1085,1355251803),(400225,1045,1357353872),(400229,1045,1358053362),(400758,1045,1357324082),(400799,1045,1357252991),(400921,1045,1357688584),(400958,1046,1356941783),(401262,1085,1355237177),(401299,1085,1355269162),(401331,1045,1357944243),(401504,1085,1355235632),(401582,1045,1357664594),(401600,1045,1357333021),(401604,1045,1357348255),(401622,1045,1357314414),(401721,1045,1357672536),(402309,1040,1357341123),(402309,1045,1357370940),(402309,1046,1357341118),(402309,1236,1357370816),(402847,1046,1356649705),(403018,1045,1355509499),(403135,1085,1355237300),(403983,1085,1355269027),(404411,1045,1357606138),(404411,1085,1355238327),(404576,1045,1356310005),(404649,1085,1355472321),(404795,1045,1357498313),(404953,1046,1356172201),(404962,1046,1356641429),(405106,1045,1357345009),(405224,1045,1357610895),(405671,1046,1357337989),(405690,1046,1356335318),(405804,1045,1358043278),(406119,1045,1355516902),(406290,1045,1355812968),(406514,1085,1355247741),(407044,1085,1355257810),(407457,1045,1357328040),(407824,1045,1358008402),(407883,1040,1357931765),(407883,1042,1357931688),(407883,1045,1357932453),(407975,1085,1355235861),(408122,1045,1357385176),(408216,1045,1356118989),(408216,1046,1356570111),(408230,1045,1355869842),(408367,1045,1358003739),(408386,1085,1355270385),(408439,1045,1355809030),(408439,1236,1355809078),(408878,1045,1357323264),(408946,1045,1357935046),(409215,1045,1355517549),(409579,1046,1357338029),(409579,1085,1355431448),(409943,1046,1355414496),(410194,1045,1355236007),(410195,1045,1358117535),(410543,1045,1356366417),(410823,1045,1357327739),(410963,1045,1357938887),(411098,1046,1357497823),(411472,16,1357154392),(411472,926,1357583677),(411472,1045,1357668481),(411472,1046,1357668587),(411472,1061,1357583705),(411472,2260,1357156349),(411472,11950,1357750757),(411472,12258,1357743333),(411472,12489,1357752609),(411472,15035,1355248431),(411472,15094,1357156661),(411472,15095,1357596709),(411472,15097,1357661710),(411540,1045,1355175721),(411634,1046,1356848445),(411743,1045,1357257923),(412148,1236,1355174827),(412290,1045,1358042506),(412867,1045,1357378798),(412867,1046,1357203426),(412878,1236,1356002449),(413448,1045,1357941460),(413576,1045,1357347994),(413595,1085,1355239578),(413680,1045,1357273507),(413776,1045,1357674846),(413850,1045,1357244612),(414076,1046,1355608471),(414092,1045,1357592167),(414317,1045,1357315924),(414317,1227,1357315923),(414520,1045,1355806450),(414548,1085,1355239998),(414563,1046,1357340019),(414598,1085,1355241758),(414602,1046,1357339601),(414614,1045,1355518536),(414675,1045,1357353552),(415014,1045,1355839947),(415049,1046,1357341086),(415132,1085,1355241388),(415962,1045,1355863856),(415962,1227,1355863855),(416411,1045,1357948896),(416456,1045,1358049812),(416763,1085,1355236443),(416850,1045,1357943020),(416853,1045,1357331607),(416856,1046,1357332306),(417067,1085,1355286474),(417995,1085,1355423453),(418109,1045,1358075108),(418406,1046,1357249332),(418477,1045,1355201997),(418505,1046,1357116813),(418769,1085,1355250643),(419383,1045,1357135731),(419591,1046,1355176171),(419843,1046,1357249340),(419921,1045,1357951708),(420668,1045,1357957782),(420668,1046,1357338894),(420682,1085,1355247673),(420733,1045,1357074069),(420780,1085,1355252823),(421068,1045,1355508829),(421194,1045,1358008435),(421617,1045,1357951431),(421878,1046,1355667050),(422307,1085,1355266059),(422801,1045,1356537671),(422970,1046,1357338529),(423268,1045,1355511243),(423628,1045,1357353913),(423628,1236,1357353954),(423765,1046,1356676328),(424150,1045,1357961432),(424795,1045,1357359843),(424864,1045,1357378359),(424936,1045,1357720167),(425003,1045,1356124418),(425106,1045,1355845584),(425540,1045,1357780777),(425540,1085,1355271273),(425593,1046,1357324100),(425859,1236,1355239133),(425929,1085,1355236197),(425954,1046,1357340093),(426520,1045,1357081187),(426781,1045,1357851998),(427291,1045,1357624550),(427331,1045,1357948011),(427438,1045,1357952903),(427438,1085,1355281363),(427512,1045,1356127602),(427575,1236,1357076749),(427721,1046,1357337060),(427845,1045,1357375350),(427845,1046,1357295635),(427940,1045,1357685281),(428007,1045,1355828838),(428223,1085,1355241507),(428242,1045,1357609624),(428367,1045,1355812434),(428367,1085,1355269899),(428392,1045,1357944694),(428474,1046,1357339149),(428629,1045,1357366757),(428634,1046,1356829720),(428649,1046,1357339487),(428666,1045,1357347810),(428743,1085,1355274985),(428875,1045,1355192884),(429250,1085,1355238102),(429729,1085,1355256236),(429757,1085,1355281141),(429773,1045,1357996369),(429821,1085,1355238223),(430169,1085,1355245369),(430290,1045,1357363855),(430556,1085,1355236879),(430672,1045,1355818423),(430680,1040,1355821331),(430680,1045,1357932562),(431544,1085,1355241127),(431670,1046,1357326873),(432142,1045,1358056361),(432415,1045,1355233556),(432915,1045,1357248334),(433036,1045,1357665132),(433036,1085,1355279370),(433331,1046,1357337842),(433331,1085,1355252907),(433633,1045,1357321913),(433672,1046,1357474786),(434100,1236,1355274710),(434355,1085,1355236345),(434424,1085,1355270375),(434437,1045,1357668527),(434528,1085,1355245499),(434586,1042,1357704830),(434586,1045,1357705184),(434715,1046,1357256143),(434948,1046,1357338840),(435280,1085,1355422757),(435323,1045,1357400917),(435378,1085,1355268479),(435535,1045,1357935916),(435535,1046,1357747546),(436115,1085,1355237210),(436258,1085,1355280362),(436479,1045,1357356942),(436551,1045,1357940920),(436962,1085,1355243368),(437081,1045,1357943643),(437165,1046,1357341262),(437247,1045,1357365107),(437313,1085,1355247202),(437490,1045,1357344475),(437736,1046,1357326908),(437826,1085,1355251748),(437865,1045,1356654311),(437874,1045,1357352790),(437993,1045,1357381185),(438281,1085,1355266680),(438514,1045,1357934241),(438573,1045,1357615427),(438748,1045,1357352415),(438968,1085,1355183013),(439248,1045,1358034187),(439248,1227,1358034186),(439428,1046,1357340226),(439595,1045,1357959216),(439762,1085,1355244939),(440145,1085,1355238682),(440175,1046,1357337259),(440175,1085,1355238764),(440194,1046,1357336406),(440247,1045,1357790816),(440535,1085,1355343662),(440624,1046,1355866498),(440684,1236,1357157084),(440768,1085,1355256733),(440802,1045,1357352481),(440902,1045,1357503389),(440988,1085,1355238786),(441079,1045,1357944764),(441093,1045,1355267745),(441109,1085,1355263364),(441245,1045,1358017760),(441251,1045,1357940615),(441639,1045,1357084544),(441639,1227,1357084790),(441785,1046,1357337702),(441983,1085,1355238812),(442053,1045,1357332754),(442298,1085,1355354777),(442383,1045,1357082402),(442442,1085,1355236633),(442539,1045,1357076002),(442889,1045,1357244408),(442889,1227,1357244407),(443050,1045,1357338221),(443050,1046,1357338278),(443088,1045,1357359270),(443088,1236,1355952927),(443453,1045,1357672317),(443777,1085,1355232296),(443830,1045,1357327866),(443843,1045,1357777128),(443920,1045,1357353425),(443920,1236,1357353200),(444040,1045,1358045119),(444094,1045,1357384918),(444094,1085,1355240883),(444282,1046,1356827933),(444378,1045,1357348332),(444452,1085,1355506165),(444523,1045,1358139286),(444684,1045,1357353719),(444785,1085,1355275650),(445065,1045,1357313388),(445139,1045,1357365465),(445648,1085,1355377026),(445649,1045,1357359812),(446406,1045,1357938070),(446458,1045,1357251915),(446467,1045,1356132771),(446467,1085,1355241539),(446784,1045,1357327678),(447006,1045,1357251280),(447006,1227,1357251280),(447052,1045,1355722453),(447184,1045,1357261054),(447274,1045,1355807593),(447278,1046,1357326881),(447280,1045,1357612635),(447290,1045,1357959429),(447316,1085,1355236337),(447467,1085,1355236808),(447621,1085,1355318824),(447860,1045,1357534640),(447945,1046,1357336040),(447977,1045,1357942707),(448490,1236,1357401139),(448573,1045,1357853301),(448631,1045,1357318365),(448631,1236,1357318387),(448848,1046,1357547897),(449158,1045,1355516842),(449453,1085,1355245765),(449561,1045,1357952076),(450035,1085,1355325710),(450420,1045,1357690376),(450866,1045,1357090197),(450919,1045,1358000200),(451034,1085,1355250785),(451412,1085,1355239330),(451737,1085,1355258918),(451814,1046,1357898823),(451868,1045,1357580026),(451868,1046,1357581016),(452117,1045,1355575536),(452326,1046,1357338772),(452440,1045,1357579578),(452469,1045,1357948317),(452469,1236,1357246096),(452867,1045,1355526794),(453171,1236,1357084486),(453193,1045,1357710994),(453193,1046,1356516893),(453845,1085,1355247984),(453881,1085,1355249070),(453934,1045,1357356845),(454237,1046,1357254574),(454238,1045,1357817517),(454700,1085,1355248670),(454765,1045,1357327801),(455193,1085,1355245403),(455228,1045,1357602304),(455409,1045,1357663698),(455526,1045,1357359369),(455599,1045,1357352484),(455878,1085,1355258968),(455925,1045,1357425949),(455937,1046,1357337731),(456042,1045,1357257967),(456154,1045,1357429722),(456857,1046,1357663481),(457149,1045,1356121626),(457149,1085,1355259862),(457161,1045,1356122303),(457416,1045,1356144899),(457416,1046,1357336690),(457608,1046,1357337812),(457642,1045,1355814253),(457676,1045,1357344819),(457779,1045,1355810869),(457946,1085,1355253259),(457970,1085,1355240233),(458176,1236,1355519487),(458204,1045,1356144371),(458425,1045,1357861143),(458584,1046,1357244341),(459094,1045,1357705882),(459225,1085,1355262862),(459288,1045,1357309093),(459664,1085,1355238035),(459709,1045,1357252234),(459709,1046,1357340099),(459756,1045,1357321631),(459803,1045,1356122366),(459922,1046,1357249584),(460072,1085,1355274077),(460299,1045,1357363894),(460778,1046,1356889904),(460853,1045,1357326296),(460853,1227,1357326295),(460889,1045,1357380542),(460906,1045,1357353315),(460906,1085,1355247696),(461273,1045,1358103385),(461284,1236,1357944149),(461334,1045,1357247853),(461412,1045,1355509208),(461580,1045,1355198133),(462129,1085,1355236796),(462210,1045,1357655911),(462508,1085,1355245067),(462830,1045,1357078974),(462903,1085,1355265928),(462988,1046,1357338807),(463277,1045,1358002066),(463277,1085,1355315388),(463577,1045,1355507882),(463983,1045,1357353119),(463996,1046,1357341358),(464005,1085,1355274673),(464040,1045,1357269640),(464101,1045,1357662456),(464111,1045,1357841279),(464160,1045,1358084365),(464390,1045,1357327891),(464390,1236,1357594859),(464873,1045,1357328112),(465100,1046,1357339055),(465123,1045,1357351189),(465149,1045,1357348030),(465449,1045,1357387465),(465502,1085,1355182572),(465765,1045,1357938316),(465765,1046,1357336172),(465939,1085,1355282574),(466228,1040,1355825515),(466228,1045,1355825516),(466347,1046,1357336344),(466366,1045,1357249594),(466577,1045,1357859887),(466577,1046,1357859704),(466740,1045,1357947701),(466806,1045,1358007096),(466975,1085,1355282027),(467005,1045,1357348051),(467237,1085,1355335038),(467317,1236,1355176072),(467456,1046,1357113923),(467533,1045,1357286348),(467759,1045,1355838615),(468113,1046,1357336582),(468146,1085,1355242381),(468338,1045,1357735589),(468338,1046,1357327716),(468436,1045,1355531791),(468436,1085,1355253799),(468487,1046,1357355607),(468666,1045,1357370866),(468710,1236,1355809086),(468867,1085,1355266805),(469102,1045,1357341923),(469398,1085,1355246274),(469402,1045,1358129839),(469402,1236,1356910693),(469541,1046,1357336569),(469606,1046,1357664733),(469705,1045,1357248688),(469756,1085,1355240803),(469766,1045,1357757383),(469956,1045,1357185191),(470111,1045,1357353258),(470363,1045,1357742415),(470441,1045,1357632977),(470493,1045,1357959287),(470493,1046,1357339412),(470981,1045,1355813645),(471040,1045,1357948115),(471424,1045,1357495843),(471691,1236,1357299819),(471700,1045,1356990920),(472507,1045,1357327885),(472597,1046,1357341285),(472618,1046,1355641410),(472656,1046,1357337326),(472690,1045,1357362190),(472698,1045,1357346661),(472911,1046,1357337657),(472956,1085,1355237910),(472969,1046,1357326901),(472969,1085,1355263673),(473000,1085,1355243369),(473104,1046,1357244568),(473391,1045,1357348228),(473401,1085,1355247175),(473449,1045,1357624952),(473683,1045,1357324621),(473764,1085,1355506957),(473859,1045,1357358888),(474142,1085,1355238802),(474235,1045,1357663471),(474235,1046,1357663312),(474255,1085,1355240128),(474267,1045,1357640633),(474321,1045,1357148554),(474402,1045,1357266474),(474419,1045,1355806621),(474499,1085,1355285415),(474563,1085,1355236089),(474619,1045,1357941577),(474630,1045,1357686443),(474698,1045,1358015127),(475031,1236,1355245748),(475126,1046,1357326882),(475224,1085,1355283846),(475312,1085,1355248875),(475705,1045,1357248088),(475705,1227,1357248086),(475824,1085,1355256155),(476147,1045,1357962299),(476523,1045,1357935383),(476581,1045,1357686484),(476912,1046,1357339492),(476912,1085,1355277194),(476988,1046,1356918297),(477197,1045,1357387118),(477215,1045,1355506739),(477285,1085,1355285329),(477327,1046,1357339857),(477632,1045,1357079067),(477852,1085,1355347488),(478040,1085,1355237121),(478143,1085,1355276671),(478195,1042,1357341088),(478195,1046,1357341090),(478218,1085,1355236355),(478345,1085,1355237003),(478610,1045,1355259742),(478610,1085,1355259719),(478783,1045,1357082469),(478862,1046,1357338619),(478884,1045,1357354380),(478884,1227,1357354378),(478975,1045,1357359873),(479133,1045,1355861950),(479299,1045,1357932733),(479299,1085,1355235513),(479358,1046,1357340017),(479464,1085,1355245445),(479778,1045,1357322132),(479778,1085,1355250194),(479795,1085,1355257988),(479870,1085,1355244920),(479951,1085,1355257961),(479975,1045,1355266521),(480145,1045,1358027136),(480145,1046,1357340721),(480208,1045,1355894759),(480208,1085,1355246293),(480268,1085,1355300235),(480273,1045,1357348251),(480373,1046,1357826268),(480561,1045,1355518133),(480561,1085,1355376741),(480657,1236,1355952453),(480896,1045,1357359734),(481005,1045,1358118205),(481035,1045,1357677748),(481297,1045,1357933863),(481297,1046,1355176339),(481651,1046,1356882663),(481670,1045,1358145343),(481670,1046,1358145191),(481670,1085,1355254321),(481899,1046,1357550182),(481978,1045,1355235041),(482252,1046,1356544147),(482288,1046,1357628275),(482829,1045,1355818121),(483063,1236,1357146021),(483142,1045,1355812952),(483289,1085,1355190968),(483635,1085,1355240356),(483750,1045,1355888936),(483801,1085,1355243275),(484505,1045,1357347962),(484505,1085,1355274888),(484543,1045,1357353493),(484543,1046,1357353327),(484557,1045,1355605014),(484570,1045,1357327865),(484570,1085,1355237074),(484571,1045,1355520873),(484620,1085,1355237951),(485010,1046,1357338396),(485024,1046,1357663185),(485044,1085,1355239325),(485064,1085,1355239646),(485374,1045,1358019630),(485564,1045,1357933807),(485564,1046,1357341008),(485608,1085,1355276811),(486130,1045,1357093658),(486608,1045,1358086633),(486858,1045,1357353707),(486993,1045,1357090337),(487505,1045,1356151641),(488339,1085,1355289379),(489793,1046,1357331547),(489793,1236,1357331427),(489817,1045,1357949237),(490305,1045,1357871841),(490665,1040,1355484678),(490665,1045,1355484650),(490809,1085,1355283604),(490849,1236,1355670542),(490933,1085,1355369416),(491213,1045,1357081814),(491426,1085,1355288661),(491778,1085,1355339090),(491850,1085,1355417102),(491860,1085,1355288978),(492126,15070,1355832890),(492344,1045,1355925557),(492536,1045,1355816088),(492647,1046,1356048577),(492771,1045,1357933744),(492846,1045,1355837272),(492880,1045,1358026431),(492880,7752,1358026296),(492901,1045,1357944885),(493076,1085,1355241960),(493274,1045,1357276461),(493616,1046,1357084003),(493801,1236,1355866363),(493844,1085,1355189713),(494266,1045,1357937483),(494466,1085,1355280779),(494668,1046,1355846376),(494854,1046,1357336402),(494903,1046,1357536237),(494962,1085,1355288788),(495240,1046,1357337082),(495284,1046,1357341277),(495384,1045,1357673538),(495438,1045,1355526199),(495829,1045,1357961909),(495829,1085,1355297230),(495864,1045,1357388776),(496188,1046,1357337009),(496472,1085,1355431833),(496751,1085,1355287392),(496786,1046,1357339068),(496858,1085,1355244900),(496898,1045,1357839367),(497044,1045,1357941422),(497194,1046,1357326897),(497248,1085,1355264035),(497387,1045,1355513359),(497415,1045,1357356589),(497488,1045,1355197286),(497512,1045,1355506424),(497808,1045,1358000493),(498159,1045,1355544953),(498159,1085,1355376657),(498159,1236,1355895732),(498353,1085,1355248070),(498390,1045,1357378231),(498548,1045,1357677840),(498699,1046,1357245929),(498723,1085,1355235972),(498782,1085,1355265651),(498792,1045,1358042268),(498838,1045,1357963416),(498904,1045,1356123949),(498920,1085,1355252698),(498972,1236,1357247467),(499197,1045,1357934911),(499197,1085,1355236398),(499431,1045,1355837239),(499431,1085,1355251147),(499654,1046,1357327161),(499734,1045,1357266801),(499759,1045,1355833498),(499850,1085,1355235818),(499928,1236,1357075955),(499931,1046,1357340336),(499945,1045,1357865095),(500093,1085,1355262289),(500172,1085,1355338049),(500179,1045,1355810488),(500464,1085,1355238893),(500610,1046,1357942281),(500900,1085,1355277316),(500914,1085,1355258234),(501270,1085,1355275854),(501402,1045,1357394691),(501436,1046,1357324745),(501537,1085,1355338240),(501579,1085,1355238143),(501640,1085,1355250648),(501814,1085,1355425955),(501965,1045,1357357276),(502079,1085,1355271904),(502114,1046,1357337435),(502322,1046,1357337563),(502405,1085,1355284707),(502415,1045,1357515021),(502417,1046,1356757820),(502659,1085,1355181320),(502714,1045,1357365791),(502741,1045,1356146194),(502741,1046,1357267238),(502793,1085,1355273834),(502801,1045,1358114815),(503004,1046,1357972619),(503159,1085,1355237750),(504294,1045,1357347154),(504410,1045,1355853169),(504498,1045,1357327769),(504533,1085,1355248187),(504734,1045,1358126530),(504798,1046,1357332342),(504798,1236,1357331299),(504874,1085,1355276686),(505032,1045,1357938335),(505223,1046,1355696400),(505235,1045,1357353332),(505308,1045,1357249121),(505360,1046,1357144106),(505360,1236,1357258750),(505382,1085,1355353460),(505428,1045,1357978118),(505428,1085,1355246438),(505644,1045,1355844218),(505644,1046,1357336879),(505644,1085,1355242350),(505740,1085,1355291348),(505898,1045,1356124670),(506327,1236,1357172203),(506692,1085,1355177555),(506887,1045,1356192869),(507113,1045,1357940332),(507280,1085,1355340020),(507395,1046,1357336962),(507601,1045,1357590654),(507601,1085,1355253043),(507712,1046,1357339840),(507839,1085,1355250979),(507880,1045,1357935219),(507880,1085,1355237391),(507945,1045,1357796975),(507957,1085,1355237379),(508226,1045,1357966534),(508545,1046,1357336898),(508616,1045,1357347676),(508647,1085,1355243989),(508755,1045,1357675304),(508945,1045,1357951626),(509061,1045,1357076955),(509061,1085,1355235270),(509216,1045,1358055529),(509229,1045,1355893564),(509231,1046,1355979448),(509231,1236,1357343768),(509253,1045,1357932588),(509506,1045,1358059468),(509592,1085,1355270059),(509663,1045,1358060028),(509704,1045,1357248906),(509704,1046,1357249325),(509749,1042,1357338195),(509749,1046,1357338197),(509815,1085,1355238002),(509905,1085,1355239756),(510072,1045,1357255467),(510078,1085,1355506256),(510125,1045,1357078845),(510125,1227,1356923613),(510125,1236,1357078753),(510446,1045,1357139605),(510573,1045,1357399915),(510573,1046,1355838004),(510903,1085,1355238707),(510977,1085,1355360659),(511251,1045,1357938932),(511339,1045,1357663345),(512214,1085,1355289608),(512230,1045,1357764013),(512359,1045,1357996364),(512621,1045,1357265454),(512683,1045,1357947082),(512747,575,1358012995),(512747,1046,1358013042),(512953,1045,1357252484),(513059,1045,1357933197),(513101,1045,1357073416),(513738,1040,1357336297),(513738,1045,1357946793),(513738,1046,1357336358),(514250,1045,1355812397),(514436,1045,1358074570),(514614,1045,1356226789),(514686,1085,1355272600),(514738,1085,1355236321),(514939,1085,1355184503),(514982,1045,1357669617),(515136,1045,1357306405),(516517,1045,1355541110),(516591,1045,1356134325),(516860,1085,1355260688),(516931,1045,1357370458),(517009,1085,1355360097),(517012,1085,1355243594),(517082,1236,1355811889),(517350,1045,1357936656),(517350,1046,1357336704),(517350,15070,1355514820),(517350,15107,1357936858),(517509,1046,1357336332),(517680,1045,1357322631),(517680,1046,1357324041),(517941,1045,1357687654),(518028,1085,1355269762),(518110,1046,1357340522),(519125,1040,1357095694),(519125,1045,1357095604),(519181,1045,1357383210),(519198,1045,1355258904),(519198,1085,1355237512),(519233,1045,1357256726),(519328,1045,1355506542),(519462,1046,1357337794),(519925,1045,1357364895),(519948,1045,1357365187),(520364,1085,1355272985),(520552,1045,1357971040),(520552,1236,1357971049),(520817,1085,1355248355),(520899,1045,1357338702),(520899,1046,1357338463),(520899,11876,1356129599),(522043,1045,1355834541),(522096,1085,1355235757),(522295,1045,1357243923),(522509,1236,1355842961),(522665,1045,1356123062),(522669,1236,1357088801),(522707,1085,1355237223),(522899,1085,1355240756),(522984,1085,1355265715),(523134,1236,1357239811),(523218,1045,1357327908),(523319,1046,1357937979),(523654,1045,1357108307),(523735,1045,1357675098),(523814,1045,1357177951),(523842,1085,1355266000),(523954,1046,1357337182),(524568,1045,1356116152),(524694,1045,1357942983),(525033,1045,1357328070),(525056,1045,1357415272),(525056,1085,1355338004),(525094,1045,1357245271),(525234,1045,1357337368),(525234,1046,1357337368),(525373,1046,1357254404),(525431,1045,1357958870),(526499,1046,1357339648),(526890,1045,1357305588),(527178,1045,1357933334),(527408,1045,1357359036),(528258,1045,1356244152),(528531,1236,1357362084),(528583,1045,1358007063),(528954,1045,1355706375),(528998,1042,1357936800),(528998,1045,1357936802),(529253,1045,1357076769),(529686,1045,1357756766),(529751,1085,1355240265),(529878,1085,1355237320),(529947,1045,1357934785),(529947,1085,1355240037),(529974,1046,1357142405),(530456,1045,1355265586),(530456,1085,1355265382),(530728,1046,1357129405),(531187,1085,1355238880),(531234,1085,1355244348),(531310,1085,1355236706),(531449,1236,1357247709),(531679,1085,1355251982),(531883,1045,1356143339),(531957,1045,1357917329),(532056,1085,1355243065),(532086,1085,1355242890),(532110,1045,1355514183),(532110,1227,1355514180),(532183,1085,1355237106),(532626,1045,1357087727),(532730,1085,1355242901),(532842,1085,1355245624),(533747,1046,1357337175),(534470,1045,1357751607),(534913,1045,1357390097),(534914,1085,1355341817),(534948,1085,1355247041),(535389,1045,1357934392),(535643,1236,1357082370),(535811,1085,1355318075),(536066,1085,1355228639),(536111,1045,1357438716),(536303,1046,1357324763),(536384,1045,1357359982),(536464,1085,1355237917),(536492,1045,1357660176),(536820,1045,1357933694),(537020,1045,1357245291),(537126,1085,1355244854),(537600,1085,1355248564),(537767,1045,1357582749),(537988,1085,1355239183),(537988,1236,1355239345),(538337,1045,1357244960),(539007,1045,1357348166),(539007,1085,1355256713),(539101,1045,1357934052),(539235,1085,1355238128),(539394,1045,1357945136),(539623,1236,1356132668),(539778,1045,1357946990),(539888,1085,1355243575),(540341,1085,1355428826),(540359,1045,1355771141),(540870,1045,1355832623),(540880,1045,1357352980),(540880,1046,1356436275),(540880,15080,1355939167),(540995,1045,1356721421),(541091,1045,1355871409),(541157,11945,1357939673),(541491,1085,1355260445),(541510,1085,1355250430),(542987,1045,1357932038),(543134,1236,1357334713),(543164,1236,1357144129),(543216,1085,1355186696),(543544,1045,1357823022),(543689,1045,1355270500),(543825,1045,1358027712),(544017,1236,1357529905),(544045,1045,1357671146),(544116,1045,1355273071),(544238,1045,1356188793),(545410,1085,1355244752),(545873,1085,1355255373),(546033,1045,1355946006),(546126,1085,1355319515),(546586,1045,1355819606),(546632,1045,1357958689),(546669,1045,1357077338),(546706,1045,1357324442),(546717,1045,1357335661),(546717,1046,1357335589),(546977,1045,1357947115),(547195,1085,1355287325),(547225,1046,1357340219),(547225,1085,1355262234),(547434,1085,1355177140),(547646,1046,1355840549),(547675,1085,1355236176),(547761,1045,1357389319),(547796,1045,1355830409),(547796,1046,1357337623),(547884,1085,1355286393),(547897,1045,1356232608),(548212,1045,1357937903),(548316,1045,1357353267),(548349,1046,1357326796),(548349,1236,1357326851),(548399,1045,1357395765),(548562,1045,1355507923),(548802,1085,1355312260),(548808,1045,1357353865),(549182,1046,1356055941),(549346,1042,1357337707),(549346,1046,1357337708),(550153,1045,1356296530),(550411,1045,1357959506),(550780,1045,1357934752),(551349,1046,1355175858),(551634,1045,1357956810),(552439,1236,1357331283),(553148,1046,1357336983),(553329,1085,1355499676),(553426,1045,1355919605),(553623,1040,1357337774),(553623,1045,1357337774),(553623,1046,1357337726),(553934,1046,1357264006),(554170,1045,1357335590),(554810,1045,1355862370),(555151,1046,1356152103),(555164,1085,1355236600),(555574,1236,1358140383),(555699,1085,1355329336),(555781,1045,1357151149),(556058,1085,1355285046),(556078,1045,1355547641),(556120,1045,1357365164),(556392,1045,1357933909),(556392,1085,1355247866),(556533,1045,1356198091),(556720,1045,1355243699),(556720,1085,1355243687),(556748,1045,1357800078),(556992,1085,1355235546),(557073,1045,1357075527),(557167,1085,1355246200),(557561,1045,1357245601),(557599,1045,1357345497),(557678,1046,1357338230),(558128,1045,1357935599),(558129,1045,1356743405),(558438,1085,1355412469),(558447,1045,1358130149),(558447,1236,1355343744),(558452,1045,1358008379),(558625,1045,1357335628),(558630,1045,1357610046),(558695,1045,1357335599),(558757,1045,1357084181),(558949,1046,1357339120),(559361,1045,1358123577),(559568,1045,1357945206),(559667,1045,1357316734),(560079,1046,1357340577),(560082,1085,1355239733),(560247,1236,1357856975),(560316,1085,1355279649),(560536,1085,1355267210),(560814,1085,1355237110),(560824,1045,1357971780),(561146,1046,1357254207),(561148,1045,1355838793),(561781,1045,1357246977),(561781,1046,1357340558),(562040,1045,1357356718),(563043,1046,1356101045),(563188,1236,1357261344),(563670,1045,1357075896),(563768,1045,1355627092),(563768,1227,1355627091),(563768,1236,1355627070),(564026,1045,1357352422),(564215,1085,1355237648),(564215,1236,1355237811),(564369,1046,1357340038),(564598,1045,1357936296),(564658,1085,1355252397),(565343,1045,1357360219),(565403,1046,1357341114),(565564,1045,1357082908),(565573,1045,1357938835),(565892,1045,1357746480),(565892,1046,1355176284),(566001,1046,1357336361),(566072,1085,1355241804),(566668,1045,1357353391),(566707,1045,1357765515),(567057,1045,1355248801),(567057,1085,1355383263),(567400,1046,1357336464),(567550,1045,1357356624),(567640,1046,1357338827),(567652,1045,1357933257),(567681,1046,1357337810),(567694,1045,1357694361),(567707,1045,1357348254),(567730,1045,1357659851),(568087,1045,1357778638),(568090,1045,1358074569),(568090,1046,1357210512),(568149,1085,1355242325),(568149,1236,1355242275),(568162,1045,1357955441),(568425,1045,1357600235),(568425,1085,1355240291),(568518,1045,1357328001),(569027,1045,1355928057),(569027,1227,1355928053),(569451,1045,1355842039),(569458,1045,1355823388),(569840,1045,1357363438),(569986,1045,1358040323),(569986,1085,1355278771),(570612,1045,1357529624),(570624,1045,1357359231),(570626,1085,1355284027),(570634,1046,1357340348),(570737,1045,1357368223),(570737,1227,1357368223),(570737,11937,1357291868),(570737,14961,1357225616),(570737,15020,1355559615),(570737,15047,1355559726),(570737,15066,1355559666),(570737,15086,1357225546),(570737,15097,1357291762),(570737,15107,1357807216),(570737,15110,1358136061),(571157,1236,1357326876),(571174,1045,1357976298),(571380,1085,1355238590),(571647,1085,1355279562),(571647,1236,1355811416),(571884,1045,1355821455),(571931,1045,1357669925),(571946,1045,1358140088),(571956,1046,1357333797),(572042,1046,1357338219),(572094,1085,1355264417),(572490,1045,1357366063),(572517,1045,1357947385),(573040,1085,1355254032),(573124,1046,1357340603),(573240,1045,1357948983),(573410,1046,1357340459),(573529,1046,1355813557),(573571,1045,1357767959),(573847,1046,1357340898),(573958,1045,1357932864),(574126,1045,1355845867),(574518,1045,1357614549),(575139,1085,1355236246),(575489,1236,1357613351),(575628,1045,1357753169),(575675,1045,1357630168),(575675,1227,1357630150),(575748,1045,1357090014),(575781,1045,1357257802),(575837,1045,1357352562),(575837,1085,1355270198),(575926,1045,1358099272),(576101,1045,1357911951),(576173,1045,1355888348),(576270,1085,1355243027),(576797,1046,1357338750),(576844,1046,1355783263),(576850,1045,1357323894),(576911,1085,1355255397),(577080,1085,1355243691),(577142,1045,1355506776),(577410,1045,1357347811),(577842,1046,1355834953),(578011,15091,1356402295),(578276,1085,1355244081),(578490,1045,1357253451),(578848,1085,1355254342),(579101,1045,1357353001),(579101,11952,1357950154),(579154,1046,1357324108),(579866,1045,1357343783),(579866,1227,1357343781),(579866,1236,1357343912),(580047,1046,1357338059),(580167,1045,1357936700),(580457,1045,1357248947),(580681,1045,1357346899),(580955,1045,1357364833),(581343,1045,1356138173),(581578,1045,1357948556),(581662,1085,1355241127),(581748,1046,1357340204),(582041,1046,1356216698),(582374,1045,1357264737),(582608,1045,1357975249),(582870,1085,1355247161),(583081,1046,1357246283),(583863,1045,1357335298),(583893,1045,1357832756),(583896,1045,1357685929),(584056,1046,1357340047),(584250,1046,1357662389),(584609,1045,1357357281),(584622,1045,1355541866),(584622,1085,1355250938),(585186,1045,1356129503),(585264,1045,1358015378),(585416,1236,1355846841),(585583,1085,1355242729),(585636,1045,1357947668),(585922,1046,1357338164),(585995,1046,1357179094),(585995,1236,1357151036),(586001,1045,1355176031),(586265,1085,1355238666),(586345,1045,1357350953),(586345,1227,1357350952),(586787,1045,1357685735),(588017,1085,1355246050),(588241,1045,1357686259),(588511,1045,1357327659),(588511,1046,1357249335),(588752,1045,1356308007),(588970,1085,1355275401),(588970,1236,1355189807),(590297,1045,1357372703),(590456,1227,1357102430),(590456,1236,1357102390),(590573,1045,1357779788),(590960,1045,1357330453),(591171,1046,1357340206),(591890,1046,1356813926),(592320,1046,1357339342),(592393,1045,1357767558),(592621,1085,1355244490),(592751,1045,1355543743),(592751,1085,1355247948),(593285,1046,1357760154),(593424,1085,1355259296),(593595,1045,1358150449),(593714,1085,1355225326),(593841,1046,1355843955),(593848,1045,1357780830),(594100,1046,1355402079),(595004,1085,1355243933),(595004,1236,1357387614),(595135,1046,1357334332),(595326,1085,1355238606),(595403,1085,1355240265),(595752,1045,1357304213),(596017,1045,1357944865),(596066,1046,1357168952),(596080,1046,1357337709),(596298,1046,1357178323),(596454,1045,1357587773),(596454,1046,1357243699),(596545,1045,1357348152),(596561,1045,1356184807),(596703,1045,1357087858),(597194,1045,1355872139),(597351,1085,1355241097),(597373,1045,1357698521),(597373,1227,1357698520),(597373,1236,1357698632),(597753,1045,1357780991),(597753,1227,1357780988),(598069,1045,1356120912),(598260,1045,1357357015),(598777,1045,1357366803),(598973,1085,1355246775),(599983,1045,1357384427),(600206,1045,1357306346),(600383,1045,1357342346),(600383,1085,1355235696),(600419,1045,1357932898),(600498,1045,1357418372),(600539,1045,1357359417),(600576,1045,1355274127),(600630,1045,1357365978),(600943,1046,1355176329),(600947,1045,1357936922),(601150,1045,1357586689),(601382,1045,1356150787),(601382,1085,1355240622),(603462,1046,1355841308),(603595,1045,1357352544),(604189,1085,1355256987),(604297,1085,1355286380),(604376,1045,1357950215),(604555,1045,1358007888),(604783,1045,1357330058),(604843,1085,1355241608),(604843,1236,1355241857),(604918,1236,1357492403),(605050,1045,1357335537),(605137,1236,1357363809),(605393,1045,1357950542),(605565,1085,1355441831),(606122,1046,1356501517),(606330,1045,1357502967),(606654,1085,1355236684),(606997,1045,1358123456),(607386,16,1357245523),(607386,1046,1357245478),(608799,1045,1357938016),(608799,1046,1357336281),(609148,1045,1357114001),(610046,1045,1357844370),(610082,1045,1358019508),(610123,1085,1355242356),(610268,1236,1357404537),(610957,1046,1357560867),(611109,1046,1355837621),(611338,1045,1357594155),(611338,15085,1356041736),(611396,1045,1357949575),(611725,1045,1355928806),(611746,1046,1355851120),(611794,1045,1357190245),(612417,1085,1355261415),(612899,1045,1357253929),(613069,1085,1355235279),(613275,1045,1357078208),(613948,1045,1355808310),(614760,1045,1357615097),(614974,1085,1355341054),(615472,1045,1357752124),(616996,1045,1357182710),(617197,1046,1357329654),(617209,1046,1357254476),(617229,1085,1355441840),(617299,1045,1357250993),(617928,1046,1357326817),(617941,1045,1355558846),(617941,1227,1355558843),(617960,1045,1357446345),(618052,1045,1357330426),(618193,1045,1357692161),(618903,1085,1355252189),(620694,1045,1357778578),(621089,1085,1355269334),(622248,1046,1357337389),(622442,1045,1358014838),(622698,1085,1355256028),(623107,1045,1355839203),(623375,1045,1357353015),(623412,1045,1357373385),(624374,1045,1357329832),(624701,1045,1357347881),(624701,1085,1355236604),(624845,1045,1357075664),(627136,1085,1355235926),(627259,1045,1357353473),(627475,1085,1355244793),(627914,1045,1355841123),(628236,1085,1355246868),(628319,1085,1355243221),(628338,1236,1357324842),(628504,1085,1355242477),(628629,1085,1355237488),(628654,1046,1357333657),(628769,1085,1355238594),(628775,1045,1357244495),(628825,1045,1357082490),(628981,1045,1357249326),(629084,1045,1356147821),(629098,1085,1355273418),(629134,1085,1355240617),(629175,1045,1355913460),(629296,1085,1355286008),(629304,1085,1355241893),(629470,1045,1357374539),(629470,1085,1355265935),(629484,1085,1355249660),(630255,1045,1357938531),(630255,1085,1355242390),(630297,1085,1355238785),(630437,1045,1355245575),(630444,1046,1357361429),(630444,1085,1355291538),(630593,1045,1357496782),(630623,1045,1357935825),(630786,1085,1355270556),(630933,1085,1355237462),(631054,1045,1357066129),(631054,1046,1358125265),(631054,1227,1357066128),(631127,1045,1357767522),(631550,1085,1355241655),(631567,1045,1355515172),(632985,1236,1357608814),(633045,1085,1355284510),(633117,1085,1355253995),(633767,1045,1357942764),(635973,1045,1358110339),(636338,1045,1357778456),(636527,1236,1357090642),(636532,1045,1357885751),(636532,1046,1357340085),(636564,1085,1355250685),(636854,1045,1357942666),(636854,1227,1355845980),(636899,1085,1355288838),(636931,1085,1355324401),(637075,1045,1357385825),(637435,1045,1357971066),(637766,1045,1355508798),(637837,1045,1357245575),(637959,1045,1355601883),(638364,1085,1355367549),(638396,1045,1357253286),(638551,1085,1355325664),(638645,1045,1357869271),(638660,1085,1355253208),(639266,1045,1357389535),(639466,1045,1358028261),(639466,1227,1358028260),(639514,1045,1357375941),(639514,1236,1357247253),(639535,1045,1357596724),(639535,1046,1357256654),(639652,1045,1355807286),(639762,1045,1357327841),(639762,1227,1357327807),(639762,1236,1357327843),(639861,1045,1355877584),(639929,1045,1357933629),(640025,1045,1358029568),(640085,1045,1355263616),(640299,1045,1357849588),(640385,1045,1358111406),(640615,1045,1357320239),(640615,1085,1355433379),(640659,1045,1357327480),(641031,1045,1357940828),(641577,1085,1355239738),(642262,1045,1356178164),(642262,1046,1357254245),(642392,1045,1357933140),(642909,1045,1357779095),(643012,1045,1357372331),(643337,1046,1357336467),(643513,1045,1357335130),(643513,1046,1357335132),(643631,1085,1355239094),(643779,1046,1357340392),(643877,1045,1357742685),(643927,1085,1355253284),(644089,1045,1355886578),(644205,1045,1357869440),(644326,1045,1355808326),(644326,1227,1355808322),(644542,1085,1355239942),(644629,1085,1355240984),(644668,1085,1355237695),(644690,1046,1357341188),(644931,1045,1358016606),(644931,1236,1358016566),(645012,1045,1356639270),(645258,1085,1355380625),(645362,1085,1355282910),(645460,1046,1355176340),(645463,1085,1355331469),(645530,1045,1357090780),(645640,1046,1357339918),(645879,1045,1357969508),(645894,1085,1355249173),(645910,1046,1356890522),(645946,1046,1356010777),(645974,1045,1357668304),(645974,13278,1357434772),(645996,1045,1357246133),(646019,1085,1355381319),(646036,1046,1356829692),(646139,1236,1355418939),(646167,1045,1357943670),(646535,1046,1357945549),(646543,1046,1356344914),(646543,1085,1355303739),(646598,1085,1355241016),(646685,1045,1357932941),(646779,1085,1355237323),(647072,1045,1358130074),(647086,1085,1355248239),(647124,1085,1355265851),(647203,1046,1357338850),(647327,1045,1357358024),(647416,1046,1357337337),(647629,1046,1357004367),(647766,1046,1357336219),(647854,1045,1356399834),(648055,1040,1357337439),(648055,1042,1357337399),(648055,1045,1357337439),(648055,1046,1357337447),(648205,1045,1357949411),(648205,1046,1357339797),(648205,1085,1355273848),(648206,1045,1355346738),(648206,1227,1355346735),(648351,1085,1355241738),(648362,1045,1357422276),(648486,1085,1355272805),(648534,1085,1355251353),(648622,1085,1355238495),(649428,1045,1355882229),(649472,1045,1357987662),(649522,1085,1355270948),(649628,1045,1355506521),(649664,1085,1355237783),(649855,1046,1357338661),(649913,1045,1356491092),(649964,1046,1355824913),(650830,1045,1357760711),(650963,1045,1358140897),(650968,1085,1355275909),(651249,1046,1357604260),(651344,1085,1355238932),(651648,1085,1355177890),(651928,1085,1355270263),(652068,1085,1355237239),(652111,1085,1355246358),(652128,1236,1355214050),(652408,1085,1355288523),(652665,1046,1357327174),(652665,1085,1355293425),(652940,1085,1355236952),(653043,1045,1357613847),(653331,1046,1355855557),(653437,1045,1357372268),(653476,1045,1357256362),(653514,1045,1357435463),(653607,1045,1357398727),(653690,1045,1358123823),(653690,1046,1357337993),(653851,1045,1357945894),(654066,1046,1357337625),(654136,1085,1355235942),(654315,1045,1355891803),(654677,1236,1357933781),(654800,1085,1355241484),(655004,1045,1358011244),(655102,1045,1357271188),(655264,1045,1357622752),(655264,1227,1357622750),(655277,1085,1355355715),(655432,1085,1355283824),(655440,1046,1357339093),(655472,1085,1355460439),(655473,1085,1355258269),(655490,1046,1357324742),(655490,1236,1357324937),(655587,1045,1357948111),(655587,1085,1355338355),(655587,1236,1357142768),(655618,1045,1357948023),(655630,1045,1357400160),(655641,1045,1357956913),(655670,1045,1357947532),(655685,1236,1357086543),(655728,1045,1357612443),(655934,1085,1355236253),(655940,1046,1357338477),(655956,1046,1355847934),(656176,1085,1355245008),(656219,1085,1355256550),(656483,1045,1356130761),(656644,1085,1355373253),(656834,1045,1357971160),(656837,1085,1355331209),(656839,1085,1355240213),(656858,1042,1357939264),(656858,1045,1357939267),(656929,1085,1355276487),(657040,1045,1357289490),(657079,1045,1356122654),(657321,1045,1357735178),(657624,1085,1355286752),(657650,1085,1355330559),(657734,1045,1355861485),(657926,1085,1355285770),(658066,1045,1357953935),(658167,1045,1357441672),(658167,1227,1357441669),(658219,1046,1355860811),(658321,1045,1357353702),(658381,1045,1358138137),(658540,1085,1355240792),(658550,1085,1355254135),(658556,1085,1355243325),(658667,1046,1357339504),(658676,1046,1357661699),(658837,1045,1355832620),(658950,1085,1355244155),(659031,1045,1355843986),(659552,1046,1357337083),(659694,1085,1355244060),(659845,1085,1355264885),(660228,1046,1357280807),(660293,1045,1357370713),(660298,1085,1355176708),(660349,1045,1356122385),(660809,1085,1355247711),(660819,1045,1357933478),(660970,1046,1355810726),(661023,1085,1355369512),(661062,1085,1355243588),(661080,1085,1355193615),(661178,1085,1355259188),(661283,1085,1355236335),(661361,1085,1355256450),(661433,1046,1355808341),(661444,1046,1357337025),(661444,1085,1355240510),(661541,1045,1357397952),(661541,1046,1356298860),(662155,1085,1355364618),(662226,1045,1355810038),(662242,1045,1357347265),(662564,1085,1355237320),(662786,1236,1355257483),(662903,1045,1357497040),(663042,1085,1355277022),(663308,1045,1357335789),(663308,1085,1355240437),(663633,1045,1357364316),(663664,1085,1355242341),(663835,1045,1356129025),(663868,1085,1355244279),(663879,1040,1355812162),(663879,1045,1355812166),(664710,1045,1357941376),(664823,1045,1357345027),(664933,1085,1355268941),(665054,1045,1357352819),(665488,1046,1356749972),(665616,1046,1355727507),(665687,1046,1357339629),(665722,1045,1357244991),(665888,1045,1355862534),(665926,1085,1355237023),(666016,1085,1355237058),(666072,1085,1355176448),(666079,1085,1355327111),(666174,1085,1355238381),(666243,1045,1357882870),(666367,1045,1357361721),(666378,1045,1357691915),(666422,1085,1355367882),(666468,1045,1358038783),(666969,1046,1355834832),(667056,1085,1355236499),(667255,1045,1356124586),(667455,1045,1357518440),(667693,1085,1355235384),(667772,1045,1355840648),(667772,1085,1355256366),(667815,1045,1357385625),(668128,1045,1357359484),(668260,1085,1355201603),(668627,1085,1355243673),(668734,1085,1355237140),(668853,1046,1355838979),(668923,1046,1355852859),(668967,1085,1355236819),(668981,1045,1357073712),(669024,1045,1358003808),(669037,1085,1355275233),(669188,1046,1357326855),(669361,1085,1355238581),(669381,1045,1357585725),(669450,1045,1357601960),(669477,1085,1355175837),(669510,1085,1355236655),(669641,1085,1355449382),(669754,1045,1356140931),(669819,1085,1355240153),(669930,1045,1356126926),(669939,1046,1355809866),(670030,1045,1357399559),(670030,1085,1355239088),(670132,1045,1357678542),(670135,1045,1358084758),(670135,1046,1357910719),(670167,1046,1357258378),(670176,1085,1355237787),(670251,1045,1357941472),(670342,1045,1357347383),(670342,1236,1357936452),(670535,1045,1357425435),(670535,1085,1355254571),(670600,1045,1358016853),(670698,1045,1357158182),(670787,1045,1357353469),(670870,1045,1355185661),(670900,1046,1355810012),(671080,1085,1355263592),(671375,1085,1355237805),(671387,1045,1355849886),(672082,1045,1357247863),(672236,1236,1357266720),(672239,1085,1355245578),(672903,1046,1357339193),(673087,1085,1355240178),(673209,1085,1355235870),(673376,1045,1357934473),(673577,1045,1357114638),(673577,1046,1356422598),(673747,1046,1357768641),(673749,1045,1356232746),(673775,1085,1355258738),(673795,1045,1357951021),(674382,1045,1355881067),(674382,1227,1355881064),(674773,1085,1355235410),(675049,1045,1357390119),(675061,1045,1357262562),(675182,1085,1355245964),(675246,1045,1356180976),(675928,1085,1355237106),(676194,1045,1357938144),(676332,1085,1355253714),(676437,1045,1357327858),(676437,1046,1357337388),(676667,1045,1357933861),(676667,1046,1357326899),(677365,1045,1357270726),(677470,1045,1357755642),(677470,1236,1355935783),(677641,1045,1358044340),(677874,1045,1356123562),(677920,1045,1355853754),(678062,1045,1357324059),(678062,1046,1357324083),(678285,1045,1357626091),(678511,1046,1355829573),(678528,1045,1357316445),(678660,1046,1355855319),(678713,1046,1355811910),(678725,1236,1355188457),(678771,1045,1357245740),(678771,1046,1357245493),(678918,1045,1357943925),(678931,1085,1355249000),(679058,1085,1355253038),(679090,1085,1355247357),(679094,1085,1355235517),(679120,1045,1357253226),(679143,1045,1358012992),(679415,1085,1355262254),(679794,1045,1355531013),(679953,1045,1357957989),(680143,1046,1355864889),(680308,1045,1357389577),(680592,1085,1355238355),(680628,1045,1357932039),(680657,1045,1358024619),(680771,1085,1355249927),(680796,1085,1355280651),(680823,1085,1355247605),(681029,1045,1357965417),(681131,1046,1355887317),(681654,1085,1355241645),(681816,1045,1356148125),(681909,1045,1357945434),(682321,1045,1356130450),(682469,1045,1357958666),(682488,1085,1355276731),(682626,1045,1357348029),(682936,1045,1357323977),(683038,1045,1355517665),(683188,1046,1357324106),(683562,1045,1357957237),(683594,1085,1355238235),(683632,1085,1355280928),(683759,1045,1357510483),(683799,1045,1357347580),(683901,1085,1355240973),(683935,1046,1357934472),(684041,1085,1355256619),(684150,1045,1357117424),(684150,1227,1357117421),(684160,1045,1357365852),(684192,1045,1357935565),(684192,1046,1357336408),(684269,1085,1355255450),(684314,1045,1357676803),(684323,1045,1355867172),(684425,1045,1357871510),(684447,1085,1355247433),(684480,1085,1355318557),(684505,1085,1355320954),(684732,1085,1355265053),(684999,1045,1357324466),(685158,1045,1357096421),(685440,1045,1357327658),(685486,1045,1357248905),(685661,1045,1356068827),(686310,1046,1355841546),(686312,1085,1355235449),(686554,1085,1355254444),(686653,1085,1355236719),(686660,1045,1355841999),(686908,1045,1356144424),(686942,1040,1357339584),(686942,1045,1357339584),(686942,1046,1357339916),(687099,1046,1355831046),(687144,1085,1355287083),(687390,1085,1355339296),(687715,1046,1357663053),(687821,1085,1355239362),(687880,1045,1357341112),(687880,1046,1357340646),(688026,1085,1355236958),(688295,1046,1358146892),(688349,1045,1357379296),(688566,15078,1355855053),(688644,1085,1355237645),(688783,1045,1355841078),(689052,1046,1357341440),(689097,1045,1355504901),(689312,1085,1355254597),(689787,1085,1355319883),(689972,1045,1357676048),(690009,1046,1355874164),(690111,1046,1355842094),(690858,1236,1355268442),(690951,1085,1355256411),(691037,1085,1355505641),(691264,1046,1356462881),(691578,1045,1358142856),(691578,1227,1357522595),(691595,1046,1357339955),(691710,1045,1357777378),(691772,1045,1357245032),(691919,1045,1355847961),(692039,1045,1357226786),(692186,1045,1357308520),(692388,1045,1357100909),(692541,1045,1357631654),(692586,1045,1357693584),(692724,1085,1355236428),(693142,1085,1355323808),(693400,1040,1355260512),(693400,1045,1355260526),(693414,1085,1355301211),(693502,1085,1355257927),(693542,1085,1355288833),(693612,1045,1357327942),(694014,1046,1357255802),(694232,1085,1355248150),(694308,1085,1355236285),(694312,1085,1355241046),(694333,1085,1355236827),(694378,1085,1355277803),(694530,1045,1357878300),(694530,1046,1355836026),(694542,1045,1357250561),(694823,1045,1357750666),(694927,1085,1355244455),(695087,1085,1355236968),(695163,1085,1355253611),(695209,1085,1355237183),(695259,1042,1357341528),(695259,1046,1357341529),(695530,1085,1355244398),(695615,1236,1357135816),(695619,1045,1355832146),(696040,1045,1357962090),(696393,1045,1357621221),(696499,1046,1355959837),(696567,1046,1357326897),(696614,1045,1357340692),(696614,1046,1357340691),(697246,1085,1355239261),(697357,1045,1358045349),(697544,1085,1355248198),(698308,1085,1355362310),(698387,1045,1357951318),(698474,1045,1357759776),(698787,1085,1355356084),(699464,1045,1355831899),(699834,1045,1357359110),(700535,1085,1355279896),(700971,1085,1355244886),(701112,1045,1357596644),(701283,1045,1357364287),(701283,11950,1357960709),(701542,1045,1355302547),(701542,1085,1355302561),(702248,1085,1355243627),(702481,1045,1356130431),(703245,1085,1355270682),(703255,1046,1357337143),(703289,1045,1357947532),(703413,1085,1355271894),(703417,1042,1357940571),(703417,1045,1357940572),(703489,1085,1355294307),(703501,1045,1357523721),(703673,1045,1357402046),(703948,1045,1355851483),(704014,1045,1357663315),(704159,1236,1355873556),(704211,1085,1355342335),(704289,1045,1357253103),(704303,1045,1355816855),(704347,1045,1357973840),(704515,1045,1358020455),(704944,1046,1357900759),(704960,1085,1355237544),(705113,1045,1358009225),(705338,1045,1355841393),(705347,1085,1355190302),(707636,1085,1355249474),(707703,1085,1355326414),(707853,1045,1357581665),(708229,1045,1355634400),(708229,1046,1355384678),(708229,1236,1355460412),(708525,1045,1357769604),(708591,1085,1355425362),(708768,1045,1357328014),(709067,1045,1357963661),(709563,1085,1355263521),(709731,1236,1356218547),(709777,1045,1357144189),(709780,1046,1358109491),(709798,1045,1358004689),(710019,1085,1355299878),(710139,1085,1355252257),(710314,1046,1357080618),(710531,1085,1355242286),(710567,1045,1357950273),(710650,1085,1355246370),(710909,1045,1357323989),(710909,1046,1357324165),(711204,1045,1357943343),(711204,1085,1355241081),(711204,1236,1355241102),(711613,1045,1357361810),(711736,1085,1355251466),(711796,1045,1357590566),(712046,1085,1356188091),(712091,1045,1355807522),(712267,1045,1357931752),(712389,1045,1356130433),(712389,1085,1355239165),(712492,1085,1355175858),(712784,1236,1355846317),(712872,1045,1357864915),(713679,1046,1356714854),(713705,1045,1357604021),(713935,1046,1357335871),(714099,1046,1357254404),(714099,1085,1355333718),(714163,1085,1355238501),(714441,1045,1357328022),(714441,1236,1357329429),(714684,1045,1357829695),(714684,1085,1355244167),(714713,1045,1357328002),(714806,1045,1358043732),(715144,1045,1357965361),(715260,1045,1357376415),(715685,1085,1355243568),(715794,1045,1355368252),(716135,1045,1355840324),(716135,1046,1357336299),(716586,1085,1355200389),(717208,1045,1357602333),(717645,1045,1357335529),(717789,1045,1357599504),(718227,1046,1356358825),(718273,1085,1355240323),(718400,1236,1357475898),(718697,1046,1357244575),(718974,1045,1357807817),(718974,1046,1357807273),(719118,1045,1357347809),(719158,1045,1357952580),(719267,1085,1355328759),(719295,1085,1355419002),(719356,1085,1355252059),(719428,1085,1355238225),(719669,1045,1356037856),(719745,1045,1355505265),(719841,1045,1357335471),(720149,1085,1355249698),(720324,1045,1356122709),(720617,1046,1355914749),(720660,1085,1355389294),(720721,1045,1355282596),(721043,1046,1357075998),(721044,1085,1355241040),(721322,1085,1355249119),(721583,1045,1358129826),(721583,1236,1355453930),(721914,1045,1357373704),(721981,1042,1357338570),(721981,1046,1357338572),(722292,1045,1357328022),(722638,1045,1356124365),(722638,1046,1355852323),(722655,1236,1357297803),(722840,1045,1357327877),(722894,1085,1355237193),(722917,1085,1355236561),(722955,1045,1357962131),(723172,1045,1357606376),(723235,1045,1357431900),(723397,1085,1355243690),(723440,1045,1355176984),(723636,1045,1355831092),(723811,1085,1355238201),(724956,1085,1355255447),(725603,1085,1355262322),(725604,1046,1357433036),(725659,1046,1357942933),(725952,1085,1355281902),(726074,1045,1357094436),(726151,1046,1356017443),(726209,1045,1355848251),(726264,1085,1355266915),(726340,1046,1355933649),(726609,1045,1357593465),(726731,1085,1355277376),(726741,1046,1355853377),(726927,1046,1355758783),(726950,1045,1358140402),(727544,1045,1357954227),(727886,1236,1357283803),(728218,1045,1355279034),(728231,1046,1355847353),(728239,1045,1357359012),(728264,1045,1355858507),(728372,1046,1355840838),(728507,1045,1357931404),(728530,1045,1357934279),(728583,1046,1357339456),(729022,1045,1356202841),(729214,1045,1355853047),(729241,1046,1357326898),(729397,1085,1355278717),(729825,1045,1357327946),(730058,1085,1355236479),(730150,1046,1356246174),(730150,1085,1355239547),(730270,1045,1357324588),(730274,1045,1355272765),(730274,1085,1355272780),(730508,1045,1357959126),(730666,1046,1357933975),(730689,1045,1357359058),(730887,1085,1355237841),(730973,1085,1355239365),(731004,1085,1355271038),(731026,1085,1355245811),(731141,1085,1355246896),(731770,1046,1355807977),(731923,1046,1356336042),(732738,1085,1355242363),(732851,1085,1355268546),(733104,1045,1357968638),(733114,1085,1355249823),(733188,1085,1355279673),(733228,1046,1355835177),(733498,1085,1355264753),(733642,1085,1355244355),(733657,1046,1357339469),(734008,1045,1357593908),(734267,1046,1355970503),(734583,1045,1355845514),(734583,1085,1355238207),(734617,1085,1355248993),(734694,1085,1355264134),(734848,1045,1355831125),(734876,1085,1355236590),(735046,1045,1355983864),(735513,1045,1357014247),(735532,1045,1357669886),(735770,1045,1355845315),(736219,1085,1355240778),(736231,1046,1355883401),(736305,1085,1355252193),(736465,1046,1355851063),(736568,1046,1355844293),(736657,1085,1355256349),(737167,1236,1357761788),(737212,1046,1357340988),(737325,1085,1355236375),(737639,1085,1355366011),(737667,1085,1355315033),(737787,1085,1357530880),(737918,1085,1355276701),(738041,1045,1358008295),(738041,1085,1355249844),(738136,1085,1355250085),(738168,1085,1355245926),(738283,1046,1355816005),(738605,1045,1357402051),(738709,1045,1358002131),(738881,1046,1355806372),(738892,1045,1357959138),(738967,1085,1355247103),(739067,1045,1357970164),(739067,1046,1355877007),(739415,14,1357583603),(739415,305,1357579210),(739415,1045,1357675480),(739415,1046,1357845699),(739415,13255,1357579223),(739415,15097,1357575023),(739651,250,1355436991),(739651,1045,1357916168),(739651,1046,1357930591),(739651,2260,1355176588),(739651,12305,1355346543),(739651,15076,1355774387),(739651,15097,1357311144),(739651,15108,1357767971),(739702,1045,1357326686),(739702,1227,1357326684),(739772,1045,1357332468),(739772,1046,1357077341),(739838,1045,1357381920),(740284,1046,1355847588),(740756,1045,1357335435),(740756,1085,1355237280),(741263,1046,1357336429),(741290,1045,1357860662),(741303,1085,1355240234),(741368,1045,1357945858),(741368,1085,1355442909),(741389,1085,1355283992),(741594,1085,1355263412),(742228,1045,1357255088),(742228,1085,1355259849),(742415,1045,1355876741),(742768,1085,1355243949),(742860,1046,1355808751),(743306,1236,1357086657),(743430,1085,1355281228),(743661,1045,1357359265),(743866,1085,1355250866),(743978,1085,1355237744),(744478,1045,1358027759),(744747,1045,1357247564),(744747,1085,1355243465),(744966,1045,1355874222),(744966,1046,1355874201),(745116,1085,1355262205),(745541,1085,1355375480),(745811,1045,1357930038),(745811,1227,1355511381),(745811,1236,1355511367),(746099,1045,1357347583),(746160,1045,1355508413),(746449,1046,1357326706),(746449,1085,1355240276),(746896,1045,1357932401),(746896,1046,1357338827),(746896,1085,1355256629),(747289,1085,1355176411),(747901,1045,1355821758),(748093,1085,1355236083),(748433,1045,1357365236),(748487,1046,1355828383),(748583,1045,1357934573),(748663,1085,1355269382),(748941,1045,1355839924),(749099,1085,1355239298),(749413,1085,1355349646),(749501,1046,1356895397),(749827,1085,1355253489),(750161,1046,1357341529),(750197,1085,1355249623),(750239,1045,1357353095),(750275,1085,1355236611),(750394,1085,1355248918),(750513,1046,1355864477),(750686,1085,1355430099),(750704,1045,1357950484),(750795,1046,1355976177),(750798,1046,1355839525),(751120,1046,1355977738),(751472,1085,1355349742),(751504,1045,1357792104),(751786,1085,1355468015),(751790,1085,1355371703),(752147,1045,1358041187),(752181,1085,1355236570),(752217,1085,1355241526),(752229,1085,1355280179),(752264,1045,1357938559),(752265,1046,1355815223),(752296,1085,1355236840),(752700,1085,1355244209),(752723,1085,1355245140),(752786,1045,1357359680),(752786,1085,1355244933),(752826,1045,1357329269),(752854,1045,1356554629),(752951,1045,1357684800),(752951,1046,1357336120),(753091,1042,1357337455),(753091,1046,1357337458),(753290,1085,1355277778),(753399,1045,1357661299),(753412,1085,1355242224),(753616,1045,1355238496),(753616,1085,1355238492),(753687,1045,1357366327),(753736,1046,1357337004),(753767,1045,1357245561),(753767,1227,1357245558),(754160,1045,1357624775),(754236,1045,1355515623),(754236,1085,1355237258),(754349,1085,1355312248),(754363,1045,1356147937),(754459,1046,1356576169),(754526,1046,1355837289),(754567,1045,1357424571),(754596,1085,1355285973),(755035,1046,1357336532),(755245,1045,1357245555),(755479,1045,1357337073),(755574,1046,1358005169),(755742,1085,1355273753),(755793,1085,1355243476),(755936,1045,1355528831),(755962,1045,1356729239),(756123,1085,1355244070),(756334,1045,1357401867),(756354,1045,1358103411),(756398,1045,1357609097),(756785,1085,1355239127),(756983,1046,1356389786),(757493,1085,1355255127),(757594,1085,1355275479),(757986,1085,1355255122),(758123,1045,1357943607),(758244,1085,1355256407),(758527,1085,1355346841),(758726,1045,1357781926),(758811,1085,1355197938),(758922,1085,1355237415),(759043,1040,1355970558),(759043,1045,1355970640),(759099,1045,1355348074),(759325,1045,1357359187),(759504,1085,1355261042),(759526,1045,1357939834),(759608,1045,1357370050),(759816,1045,1357784871),(759890,1046,1355838120),(760327,1046,1355824519),(760631,1046,1355845320),(760641,1045,1356122659),(760845,1085,1355236292),(760885,1045,1358037897),(761116,1045,1357328416),(761321,1045,1355522666),(761384,1045,1357334072),(761408,1045,1355512363),(761742,1045,1357350271),(761818,1085,1355251712),(761912,1085,1355238577),(761938,1085,1355287816),(762598,1046,1355869062),(762649,1046,1356199176),(762867,1046,1356071726),(762912,1045,1355541040),(762975,1045,1356154084),(762986,1085,1355262215),(763178,1046,1355875630),(763338,1085,1355275975),(763346,1085,1355278101),(763635,1045,1357963470),(763663,1046,1357328285),(763728,1046,1355935869),(763861,1085,1355240947),(763942,1045,1358099003),(763976,1085,1355338979),(763980,1085,1355250774),(763984,1045,1355835701),(764089,1045,1355180595),(764130,1085,1355250196),(764339,1045,1357353726),(764365,1046,1357326811),(764365,1085,1355236529),(764379,1045,1357101458),(764564,1085,1355332968),(764650,1046,1357337582),(764664,1085,1355271600),(764693,1085,1355239323),(764703,1085,1355240916),(764728,1045,1357353011),(764736,1046,1356676547),(764736,1085,1355383784),(764918,1045,1357760208),(764955,1085,1355427741),(764969,1085,1355236919),(765135,1046,1356671785),(765193,1046,1355846541),(765310,1045,1357336921),(765431,1045,1357347902),(765552,1085,1355244983),(765604,1085,1355251768),(765670,1045,1357084686),(765781,1046,1355837233),(766407,1045,1355587795),(766411,1045,1357073420),(766532,1045,1357953979),(766792,1085,1355317807),(766881,1045,1357343119),(767046,1045,1357269251),(767070,1085,1355252068),(767253,1085,1355203854),(767597,1045,1358046626),(767628,1085,1355241998),(767791,1045,1355518861),(767791,1085,1355290399),(767939,1085,1355245852),(767994,1045,1357379369),(768023,1046,1355828210),(768066,1046,1356067934),(768156,1045,1357994149),(768208,1085,1355262769),(768257,1045,1356137825),(768457,1045,1357329635),(768659,1045,1357932735),(768791,1045,1355769783),(768808,1046,1357330303),(768915,1045,1357399699),(768996,1085,1355269169),(769011,1085,1355237781),(769093,1046,1357325289),(769129,1045,1357347734),(769164,1085,1355242243),(769303,1045,1355605090),(769680,1045,1357403608),(769757,1045,1357409413),(769782,1046,1357326892),(770069,1046,1355885014),(770315,1046,1356030296),(770457,1085,1355268947),(770464,1045,1357358344),(770473,1046,1355948904),(770486,1085,1355368144),(770595,1045,1357401717),(770677,1085,1355247965),(770689,1046,1357475379),(770827,1045,1357962355),(770839,1046,1357327021),(771177,1045,1357763761),(771214,1045,1355529437),(771214,1085,1355444051),(771225,1045,1356121882),(771231,1236,1357335879),(771286,1045,1355824174),(771347,1045,1355859453),(771381,15094,1357419134),(771384,1040,1357339246),(771384,1045,1357339262),(771384,1046,1357339409),(771496,1085,1355238918),(771988,1085,1355238273),(772009,1045,1355526614),(772132,1046,1355896433),(772141,1046,1357254396),(772332,1042,1357339487),(772332,1046,1357340954),(772491,1085,1355801853),(772722,1085,1355238257),(772753,1085,1355234963),(772797,1045,1357955850),(772797,1046,1357338856),(772797,1085,1355336384),(773004,1085,1355270567),(773010,1045,1357510910),(773013,1046,1355823329),(773101,1046,1355838193),(773446,1085,1355238218),(773457,1046,1355849868),(773500,1085,1355242694),(773522,1045,1357401573),(773547,1045,1357932940),(773679,1046,1355719603),(773821,1045,1355509057),(774039,1045,1357402997),(774112,1085,1355247426),(774242,1046,1357340161),(774396,1085,1355186680),(774542,1085,1355361361),(774798,1045,1357345358),(774873,1045,1357928063),(774902,1085,1355240228),(774929,1045,1358051708),(775037,1045,1357358139),(775120,1045,1355259573),(775178,1085,1355334188),(775201,1085,1355178930),(775210,1046,1357336022),(775210,1085,1355282853),(775321,1085,1355359602),(775370,1085,1355393902),(775392,1045,1355843069),(775518,1045,1357097275),(775547,1046,1357839618),(775547,11950,1357933366),(775581,1085,1355238451),(775937,1085,1355243041),(776063,1085,1355241111),(776270,1085,1355256637),(776383,1046,1355859503),(776660,1046,1356573802),(776938,1045,1356139084),(776957,1085,1355242013),(776994,1085,1355269122),(777045,1046,1355859772),(777240,1045,1357358459),(777318,1085,1355236478),(777326,1046,1355809341),(777336,1085,1355345314),(777615,1085,1355262432),(777786,1085,1355236892),(777900,1045,1356480781),(778209,1085,1355235351),(778259,1045,1357938332),(778268,1085,1355239550),(779345,1046,1357338269),(779352,1046,1357339545),(779476,1045,1355541247),(779496,1085,1355351150),(779571,1046,1355835944),(779702,1085,1355236063),(779783,1046,1355507266),(779983,1045,1357388808),(780107,1085,1355294410),(780135,1045,1355809237),(780435,1045,1356125951),(780474,1046,1355834187),(780474,1085,1355314788),(780500,1085,1355252596),(780610,1045,1357954754),(780768,1085,1355239322),(780863,1045,1355527839),(781039,1045,1357956001),(781163,1046,1355861454),(781350,1045,1356976258),(781460,1085,1355239904),(781598,1085,1355240162),(781680,1085,1355250648),(781726,1085,1355359753),(781754,1045,1355681042),(781956,1045,1357530129),(782070,1045,1355732551),(782101,1085,1355246081),(782152,1085,1355248848),(782167,1046,1355849692),(782259,1085,1355261561),(782353,1046,1356824898),(782804,1045,1357349190),(782804,1227,1357349189),(782804,1236,1358106786),(782814,1085,1355422481),(782940,14,1355432869),(782940,1014,1355861404),(782940,1045,1357829190),(782940,5318,1355175122),(782940,11768,1357745961),(782940,11945,1355861433),(782940,15054,1355240504),(782940,15055,1355339789),(782940,15057,1355240476),(782940,15062,1355258544),(782940,15063,1355240431),(782940,15064,1355842249),(782940,15066,1355258476),(782940,15069,1355428606),(782940,15070,1355501638),(782940,15071,1355854413),(782940,15077,1355856786),(782940,15078,1355863236),(782940,15080,1355946696),(782940,15081,1355863301),(782940,15082,1355863395),(782940,15083,1356014195),(782940,15085,1356102294),(782940,15087,1356103734),(782940,15088,1356709990),(782940,15093,1357571563),(782940,15094,1357842905),(782940,15105,1357658322),(782940,15106,1357843488),(782940,15108,1357831117),(782940,15110,1357930264),(782940,15114,1357916899),(783551,1085,1355238704),(783691,1085,1355241651),(783805,1045,1357351635),(783823,1046,1355827547),(783853,1085,1355284101),(784087,1045,1357839511),(784186,1046,1355806975),(784292,1045,1357346977),(784301,1045,1356234415),(784370,1045,1356062297),(784515,1045,1355241943),(784515,1085,1355241959),(784628,1085,1355238229),(784707,1046,1355839005),(784728,1085,1355238402),(784813,1045,1357755300),(784872,1046,1355810093),(785074,1046,1356067558),(785119,1085,1355262395),(785250,1085,1355239295),(785264,1046,1355839937),(785393,1046,1355842507),(785415,1046,1355843643),(785475,1045,1357400616),(785527,1085,1355250951),(785596,1046,1355843150),(785853,1085,1355243625),(785882,1046,1355864556),(785954,1085,1355237011),(786143,1045,1357357465),(786175,1045,1358055924),(786218,1045,1357398806),(786218,1236,1357943626),(786254,1085,1355256501),(786347,1085,1355236736),(786452,1085,1355440307),(786470,1045,1356535479),(786494,1236,1357334209),(786767,1046,1355811341),(786863,1046,1355839353),(786876,1046,1357074184),(786890,1045,1357938859),(786890,1046,1357339924),(787011,1045,1355807829),(787011,1046,1355807775),(787046,1046,1357340494),(787213,1085,1355238200),(787235,1045,1356130488),(787306,1085,1355254830),(787339,1085,1355328910),(787376,1085,1355273574),(787425,1045,1357961686),(787454,1085,1355252812),(787484,1046,1355877381),(787520,1085,1355244073),(787661,1045,1357696597),(787661,1227,1357346295),(787716,1085,1355260689),(787798,1085,1355242374),(787842,1046,1355852115),(787892,1085,1355267448),(787940,1085,1355268770),(787968,1046,1355855357),(788063,1046,1355881766),(788104,1085,1355198885),(788114,1045,1355201680),(788162,1045,1358115748),(788266,1046,1355935609),(788326,1045,1358050196),(788355,1045,1357948871),(788412,1045,1356179437),(788460,1045,1355839381),(788484,1085,1355338688),(788506,1046,1355194159),(788544,1045,1358092580),(788544,1046,1358092572),(788565,1045,1357947789),(788602,1085,1355250826),(788621,1046,1355841793),(788621,1085,1355248734),(788635,1236,1355185566),(788699,1085,1355245497),(788808,1046,1357340258),(788970,1046,1355845995),(789016,1085,1355264653),(789228,1085,1355242209),(789262,1045,1355346191),(789297,1085,1355240138),(789557,1085,1355272194),(789561,1085,1355268365),(789573,1085,1355250210),(789619,1045,1356454134),(789626,1046,1357254864),(789738,1085,1355244081),(789748,1045,1356127687),(789921,1085,1355188379),(789996,1085,1355238114),(790045,1046,1357074100),(790106,1045,1357955429),(790221,1085,1355250732),(790344,1045,1357603538),(790442,1085,1355330346),(790575,1046,1355808753),(791008,1046,1355874585),(791080,1085,1355271144),(791470,1045,1357325673),(791474,1046,1355835041),(791720,1085,1355259125),(791801,1046,1357336746),(791858,1046,1357340108),(791909,1046,1356742141),(792002,1046,1355850751),(792061,1046,1355883404),(792062,1045,1357352678),(792179,1085,1355329417),(792264,1045,1357346546),(792264,1085,1355411930),(792370,1085,1355238013),(792562,1085,1355240141),(792753,1045,1355837871),(792753,1046,1355837856),(792788,1042,1357340584),(792788,1046,1357340662),(792864,1085,1355333735),(792898,1045,1357950656),(792922,1085,1355253994),(793011,1085,1355253753),(793483,1085,1355266189),(793547,1085,1355238016),(793582,1085,1355274032),(794047,1045,1356169221),(794047,1046,1355816714),(794254,1085,1355320190),(794367,1085,1355267279),(794384,1085,1355427244),(794563,1046,1355840420),(794722,1085,1355240760),(794745,1045,1355534829),(794816,1046,1355839480),(795139,1085,1355243296),(795357,1085,1355235380),(795381,1046,1357760293),(795393,1046,1355884294),(795618,1085,1355194487),(795754,1085,1355272116),(795807,1045,1357331487),(795916,1085,1355241986),(795992,1046,1355845551),(796012,1085,1355237538),(796066,1045,1357989871),(796182,1046,1355855898),(796278,1045,1355954733),(796293,1046,1355930814),(796293,1085,1355183616),(796621,1085,1355239249),(796658,1085,1355235514),(796772,1045,1357953909),(796990,1085,1355248138),(797096,1046,1355963943),(797106,1085,1355281269),(797294,1045,1357386875),(797341,1046,1355866714),(797437,1046,1355844323),(797467,1045,1355531172),(797489,1085,1355277938),(797567,1046,1355847383),(797668,1046,1355878422),(797853,1085,1355248981),(797929,1045,1355618662),(797954,1085,1355237555),(797967,1085,1355238422),(797986,1046,1355932802),(797989,1046,1357341390),(798028,1045,1355222645),(798086,1085,1355238595),(798118,1085,1355237435),(798288,1045,1358101066),(798394,1085,1355281634),(798476,1045,1357938109),(798659,1045,1356129672),(798720,1046,1355931096),(798985,1045,1357384555),(799217,1045,1357230382),(799309,1046,1357330094),(799684,1085,1355268282),(799877,1045,1355808278),(799895,1046,1355920870),(799905,1046,1355844274),(799905,1085,1355242969),(799919,1045,1355849604),(800186,1085,1355363989),(800283,1046,1355808772),(800292,1045,1355507853),(800306,1046,1355869609),(800421,1085,1355273022),(800503,1085,1355242460),(800611,1085,1355252883),(800616,1046,1355842547),(800787,1045,1358113203),(801061,1085,1355366480),(801082,1085,1355313469),(801426,1085,1355277833),(801506,1085,1355505551),(801657,1085,1355264643),(801664,1085,1355250166),(801707,1045,1357959396),(801707,1046,1355968932),(801716,1085,1355259635),(801731,1085,1355247829),(801788,1085,1355243876),(801849,1046,1355807481),(801953,1085,1355274433),(801978,1046,1357340333),(802263,1046,1356152418),(802263,1085,1355358588),(802348,1046,1355814870),(802777,1046,1355808242),(802787,1045,1357354823),(803074,1045,1355327923),(803074,1085,1355328079),(803098,1085,1355244884),(803270,1045,1357381936),(803470,1085,1355447008),(803593,1085,1355251655),(803660,1085,1355308276),(803877,1085,1355245281),(804037,1085,1355240810),(804189,1085,1355249669),(804201,1085,1355235336),(804316,1046,1355877353),(804431,1046,1355838916),(804661,1085,1355251180),(804667,1045,1355506015),(804713,1236,1355836791),(804832,1046,1357777424),(804957,1085,1355252374),(805060,1085,1355243885),(805420,1045,1357357919),(805614,1045,1357591825),(805654,1085,1355251812),(805708,1085,1355235373),(805860,1046,1355859743),(806141,1085,1355246126),(806197,1046,1355828444),(806300,1046,1357756816),(806445,1085,1355238358),(806743,1045,1358044593),(806790,1085,1355339348),(806870,1085,1355257393),(806960,1085,1355321985),(807084,1046,1357336272),(807278,1085,1355238920),(807321,1045,1355355336),(807321,1046,1355829428),(807477,1046,1357766088),(807642,1046,1355840333),(807711,1085,1355334536),(808110,1045,1355872189),(808132,1046,1355846388),(808229,1046,1355863272),(808260,1085,1355277588),(808297,1045,1356681997),(808365,1046,1357469472),(808422,1085,1355238069),(808430,1085,1355271650),(808500,1046,1357947439),(808561,1045,1357363634),(808730,1085,1355240972),(808752,1085,1355237108),(808760,1085,1355250674),(808804,1236,1355240271),(808830,1085,1355247714),(808847,1085,1355238561),(808887,1085,1355240834),(808911,1085,1355331027),(808942,1085,1355240831),(808951,1085,1355243321),(809001,1045,1356151467),(809001,1085,1355244059),(809008,1085,1355243013),(809037,1085,1355268994),(809108,1046,1357339110),(809136,1085,1355251715),(809146,1085,1355249473),(809162,1085,1355242786),(809333,1045,1357154694),(809338,1085,1355265933),(809341,1045,1357373437),(809341,1227,1357373437),(809364,1085,1355261405),(809372,1085,1355257295),(809613,1046,1357340268),(809626,1085,1355260081),(809641,1085,1355237667),(809711,1085,1355246050),(809749,1085,1355236626),(809751,1085,1355287387),(809857,1085,1355270364),(809868,1085,1355332185),(809876,1085,1355241392),(809880,1085,1355271465),(809888,1085,1355244397),(809924,1085,1355256082),(809926,1085,1355267452),(809982,1085,1355244436),(810012,1045,1357254789),(810033,1085,1355277540),(810098,1085,1355265962),(810126,1085,1355412371),(810214,1085,1355249946),(810250,1085,1355245593),(810266,1085,1355240444),(810276,1085,1355253441),(810291,1045,1355808341),(810349,1085,1355493684),(810369,1085,1355246676),(810410,1045,1358011292),(810410,1085,1355265010),(810460,1085,1355259859),(810476,1085,1355238233),(810501,1046,1355403529),(810518,1085,1355280817),(810542,1045,1357354007),(810559,1045,1357374016),(810559,1085,1355243716),(810582,1046,1355241852),(810652,1085,1355261857),(810658,1085,1355240898),(810679,1085,1355265834),(810700,1046,1355844649),(810727,1085,1355269038),(810775,1085,1355340329),(810837,1085,1355255480),(810855,1085,1355263575),(810958,1085,1355267210),(810983,1085,1355297047),(810999,1046,1357338940),(810999,1085,1355239988),(811079,1085,1355280224),(811100,1085,1355296867),(811121,1046,1355809007),(811121,1085,1355279981),(811198,1045,1357460454),(811198,1085,1355305118),(811217,1046,1355820204),(811265,1085,1355257872),(811280,1046,1355836318),(811303,1085,1355236854),(811356,1085,1355236970),(811383,1045,1357841235),(811383,1085,1355248041),(811392,1085,1355310183),(811466,1085,1355259761),(811480,1085,1355244826),(811483,1085,1355279927),(811493,1085,1355275475),(811515,1085,1355481232),(811522,1085,1355244970),(811523,1085,1355279857),(811537,1085,1355248238),(811562,1045,1357937823),(811562,1085,1355244223),(811600,1085,1355263354),(811613,1085,1355288658),(811669,1085,1355385469),(811698,1085,1355258155),(811719,1045,1357359407),(811736,1085,1355249788),(811820,1085,1355237036),(811857,1085,1355247911),(811904,1046,1357338885),(811969,1085,1355501182),(811985,1045,1357404647),(812034,1085,1355287967),(812064,1085,1355412517),(812081,1085,1355254020),(812114,1085,1355238555),(812183,1046,1357839337),(812202,1085,1355322058),(812263,1045,1355968078),(812446,1045,1357399519),(812506,1045,1357478054),(812512,1085,1355311936),(812728,1085,1355238714),(812780,1085,1355241657),(812962,1085,1355235717),(813140,1085,1355242068),(813213,1046,1355809561),(813427,1085,1355326022),(813507,1045,1355505775),(813769,1045,1356127819),(813858,1085,1355258695),(814036,1046,1355809076),(814162,1046,1355838366),(814184,1046,1355822759),(814220,1046,1357254173),(814249,1045,1357346868),(814249,1085,1355252373),(814271,1085,1355285158),(814330,1085,1355255122),(814881,1085,1355238613),(814985,1045,1355540887),(815172,1085,1355265121),(815336,1046,1355974035),(815390,1085,1355258105),(815436,1046,1355836623),(815456,1045,1358003179),(815474,1046,1355826739),(815562,1045,1357353544),(815949,1046,1355813819),(815971,1085,1355358980),(815973,1085,1355241915),(816029,1046,1355813314),(816114,1046,1355852078),(816129,1085,1355248303),(816203,1046,1355836428),(816309,1046,1357452653),(816376,1085,1355266929),(816510,1045,1357347925),(816609,1046,1356102264),(816774,1046,1355844763),(816930,1045,1355615431),(817240,1085,1355259392),(817252,1085,1355285873),(817339,1046,1355865766),(817744,1045,1357957585),(817950,1046,1357336601),(818015,1046,1355812516),(818037,1046,1355811684),(818099,1085,1355244803),(818170,1085,1355240430),(818236,1045,1357353171),(818241,1085,1355240066),(818320,1046,1355839528),(818338,1046,1355508161),(818401,1045,1356235974),(818401,1085,1355255075),(818407,1045,1355807438),(818410,1046,1355873035),(818671,1085,1355379681),(818705,1046,1355847110),(818849,1085,1355240117),(818867,1046,1355841585),(818966,1045,1355661892),(819259,1085,1355235766),(819379,1046,1355832720),(819563,1046,1355881046),(819660,1085,1355202458),(819808,1045,1357667884),(819833,1046,1355836323),(819836,1046,1357326806),(819973,1085,1355233160),(819992,1046,1355239356),(820067,1085,1355498299),(820158,1045,1357400905),(820196,1045,1355507876),(820211,1046,1355837811),(820408,1046,1355859140),(820629,1045,1358030821),(820643,1046,1355863573),(820676,1046,1355840252),(820701,1085,1355246330),(820710,1085,1355346626),(820740,1085,1355239067),(820782,1046,1357940036),(820806,1046,1355848722),(821168,1046,1355807432),(821368,1045,1356721339),(821457,1085,1355250610),(821607,1046,1355844886),(821612,1085,1355250475),(821626,1046,1355865441),(821639,1046,1355861773),(821696,1045,1357342514),(822072,1085,1355240869),(822116,1046,1355982637),(822241,1045,1356373022),(822241,1085,1355278242),(822356,1085,1355265955),(822364,1045,1358031147),(822415,1085,1355244137),(823029,1085,1355416759),(823051,1085,1355246974),(823054,1085,1355324975),(823095,1085,1355240492),(823124,1046,1355845101),(823188,1045,1358094129),(823188,1227,1358094128),(823188,1236,1356107018),(823211,1046,1355863065),(823212,1085,1355323376),(823238,1085,1355370751),(823327,1085,1355270588),(823414,1046,1355873899),(823485,1085,1355255954),(823547,1045,1357318363),(823702,1045,1357614136),(823753,1046,1355949612),(823901,1045,1355849068),(824019,1045,1356124766),(824026,1085,1355192248),(824057,1045,1357344735),(824274,1045,1355635590),(824305,1045,1357992665),(824346,1045,1355504672),(824483,1045,1355524493),(824558,1085,1355236703),(824559,1085,1355203216),(824601,1045,1355892452),(824680,1085,1355493270),(824693,1046,1355847011),(824841,1046,1355861978),(824924,1085,1355237991),(824980,1085,1355246967),(825006,1046,1356827348),(825034,1046,1355949501),(825236,1045,1357760362),(825319,1046,1355859503),(825460,1045,1357775936),(825620,1045,1357401879),(825621,1085,1355426882),(826293,1045,1355247931),(826293,1085,1355248135),(826326,1046,1355850237),(826817,1046,1356564663),(826844,1085,1355248871),(827091,1085,1355257591),(827139,1085,1355222691),(827179,1045,1358119565),(827246,1085,1355238585),(827259,1085,1355237196),(827263,1085,1355472597),(827296,1085,1355258857),(827369,1045,1357359731),(827421,1045,1357759945),(827428,1085,1355284318),(827509,1085,1355238976),(827724,1045,1355510252),(827732,1085,1355241067),(827786,1046,1355807198),(827810,1085,1355241769),(828022,1045,1356132915),(828068,1046,1355833963),(828167,1046,1355920356),(828214,1046,1358103555),(828294,1046,1357337038),(828397,1085,1355237805),(828451,1045,1355861438),(828451,1046,1355862259),(828838,1045,1357965073),(828848,1046,1357338348),(828859,1045,1357324668),(828888,1045,1357944659),(829003,1085,1355190501),(829085,1046,1355849493),(829126,1085,1355251840),(829325,1085,1355244623),(829429,1085,1355236226),(829580,1046,1355831808),(829634,1046,1355965366),(829664,1085,1355248374),(829688,1045,1356180786),(829723,1046,1355508790),(829774,1046,1355837377),(829930,1045,1357955825),(829942,1046,1357337504),(829963,1085,1355237474),(829974,1045,1357935054),(830152,1085,1355327408),(830171,1085,1355278139),(830356,1085,1355239205),(830588,1085,1355246841),(830649,1085,1355350228),(830658,1045,1355517031),(830658,1085,1355243235),(830961,1045,1358032712),(830999,1045,1357327792),(831057,1085,1355263823),(831065,1045,1358027520),(831185,1046,1355846671),(831318,1045,1355521256),(831328,1085,1355319581),(831488,1045,1356121603),(831583,1085,1355321587),(831597,1045,1357762957),(831607,1085,1355196537),(831702,1045,1358041560),(831746,1046,1355853081),(831867,1045,1357961612),(831922,1046,1355846602),(831933,1045,1356121958),(831951,1046,1355832527),(832118,1045,1355838033),(832160,1045,1356220211),(832236,1085,1355210369),(832308,1085,1355239594),(832369,1085,1355241568),(832402,1085,1355260344),(832425,1045,1357335917),(832425,1046,1355832843),(832474,1085,1355242499),(832481,1085,1355487138),(832510,1085,1355239139),(832513,1085,1355261305),(832521,1085,1355237039),(832575,1085,1355239579),(832604,1085,1355313988),(832612,1085,1355239071),(832640,1045,1357950188),(832640,1227,1357537357),(832640,1236,1355764882),(832650,1045,1357977837),(832669,1046,1355845749),(832706,1085,1355235747),(832795,1045,1357997107),(832814,1085,1355245173),(832821,1085,1355236508),(832905,1085,1355274546),(832958,1045,1355505110),(832958,1046,1355858093),(832999,1085,1355237233),(833030,1085,1355346965),(833065,1046,1355840399),(833080,1085,1355331067),(833091,1085,1355238254),(833132,1085,1355258039),(833156,1046,1355835687),(833165,1045,1356123172),(833182,1046,1355838000),(833207,1085,1355235259),(833282,1085,1355240485),(833341,1085,1355250439),(833372,1085,1355266506),(833379,1045,1357937690),(833455,1085,1355239248),(833471,1085,1355237950),(833498,1085,1355242173),(833540,1085,1355289771),(833567,1085,1355246449),(833599,1046,1355872510),(833700,1085,1355238337),(833820,1085,1355252386),(833850,1085,1355273120),(833855,1085,1355249275),(833867,1085,1355256767),(833920,1085,1355258263),(833984,1085,1355329839),(834014,1045,1355265322),(834014,1085,1355265321),(834055,1085,1355242718),(834153,1085,1355254832),(834211,1045,1357345361),(834231,1085,1355237336),(834285,1085,1355249876),(834290,1085,1355250096),(834316,1085,1355299713),(834375,1085,1355336597),(834414,1085,1355247463),(834458,1085,1355273622),(834467,1085,1355269918),(834536,1085,1355244530),(834564,1085,1355258985),(834595,1085,1355253763),(834649,1085,1355252443),(834705,1085,1355272047),(834723,1085,1355326465),(834725,1045,1355526439),(834725,1085,1355271995),(834753,1045,1357414575),(834876,1085,1355299751),(834947,1085,1355257324),(834965,1085,1355297285),(835027,1085,1355287215),(835036,1046,1356996580),(835052,1085,1355347224),(835057,1046,1355831451),(835123,1046,1355947270),(835180,1085,1355273527),(835215,1085,1355194286),(835222,1046,1355958879),(835227,1085,1355283204),(835509,1045,1357435252),(835594,1085,1355308230),(835598,1085,1355238885),(835615,1085,1355280908),(835658,1085,1355237401),(835719,1045,1355854686),(835915,1236,1357343516),(836030,1085,1355258175),(836074,1045,1355521075),(836123,1085,1355353705),(836137,1085,1355240510),(836279,1085,1355266426),(836302,1046,1355853377),(836796,1046,1357932994),(836895,1046,1355864941),(837094,1045,1355822465),(837275,1085,1355241055),(837385,1046,1356026120),(837439,1046,1355837197),(837442,1045,1356142837),(837829,1045,1357950590),(837843,1046,1355809210),(837880,1045,1357936060),(837990,1085,1355243846),(838088,1085,1355238164),(838189,1045,1357975471),(838310,1085,1355237967),(838408,1045,1357328009),(838665,1085,1355244090),(838994,1046,1355841395),(839099,1085,1355244289),(839129,1046,1355931671),(839250,1085,1355243272),(839306,1045,1355832591),(839306,1227,1355832590),(839350,1046,1355934682),(839562,1045,1356131885),(839587,1085,1355287606),(839688,1046,1355948652),(839726,1046,1355821333),(839742,1046,1355809657),(839975,1085,1355239336),(840081,1045,1357829069),(840083,1046,1355839689),(840278,1045,1355505569),(840344,1085,1355255335),(840625,1085,1355267490),(840754,1045,1355635365),(840766,1045,1357357274),(840967,1046,1355849039),(841074,1046,1357940173),(841085,1085,1355266016),(841268,1045,1355525052),(841358,1046,1355858329),(841507,1046,1357331494),(841529,1045,1357847471),(841588,1085,1355277875),(841651,1046,1355927354),(841782,1045,1357341242),(841831,1045,1355963464),(841982,1085,1355252767),(842006,1046,1355858691),(842012,1046,1355835733),(842076,1085,1355411958),(842279,1046,1355836024),(842283,1046,1355847491),(842362,1046,1355873384),(842774,1045,1357406959),(842972,1085,1355237920),(843004,1045,1357400311),(843557,1045,1358058134),(843557,1236,1356663456),(843650,1046,1357935310),(843732,1045,1358053894),(843895,1046,1357338467),(843997,1045,1358117614),(844049,1046,1357716723),(844895,1085,1355260191),(845173,1046,1355969199),(846692,1046,1355832199),(846908,1045,1357328107),(847340,1046,1355238207),(847340,1085,1355237243),(847589,1045,1357944324),(848091,1046,1355837255),(848219,1085,1355240925),(848236,1085,1355283711),(848563,1046,1357254242),(848601,1045,1355811009),(848601,1227,1355811001),(848601,1236,1358149187),(848957,1046,1357341204),(849014,1045,1356124044),(849492,1046,1355851406),(849500,1045,1357594172),(849798,1045,1356122226),(849805,1085,1355237332),(849872,1085,1355254499),(849968,1046,1357330654),(849988,1046,1355838735),(850005,1045,1358026901),(850054,1046,1355897553),(850359,1045,1355842629),(850411,1045,1355834459),(850641,1045,1355849229),(850663,1046,1355837280),(850748,1085,1355236142),(850851,1046,1355815679),(850855,1085,1355237527),(851034,1045,1358014595),(851322,1046,1355880782),(851605,1045,1355519336),(851639,1045,1355850455),(851650,1046,1355834478),(851809,1045,1358026510),(851848,1045,1357506244),(852239,1046,1355843741),(852371,1045,1357955984),(852442,1046,1357776485),(852542,1046,1355841742),(852636,1046,1355808780),(852768,1045,1355514437),(852835,1045,1357332110),(852896,1046,1355849530),(853468,1085,1355289361),(853614,1045,1356148298),(853813,1085,1355238369),(853909,1045,1357363771),(853909,1085,1355237790),(854058,1085,1355283791),(854314,1085,1355252761),(854351,1045,1357408503),(854480,1045,1357350436),(854480,1046,1355807696),(854638,1085,1355268098),(854765,1045,1355848380),(855245,1045,1356154490),(855411,1046,1355843820),(855535,1046,1357330631),(855902,1045,1357382715),(856062,1085,1355241629),(856117,1045,1355572317),(856331,1046,1355810717),(856417,1045,1357335481),(856417,1227,1357335446),(856478,1046,1355834726),(856507,1045,1355578000),(856680,1045,1358075684),(856681,1045,1357996834),(856684,1045,1357376655),(856700,1045,1356124167),(856886,1085,1355348241),(856892,1046,1355843873),(857148,1085,1355251115),(857596,1046,1355837640),(857681,1046,1355843036),(858000,1046,1355854695),(858798,1046,1355835504),(858841,1046,1355833068),(858943,1085,1355399813),(859019,1085,1355242562),(859061,1046,1355880223),(859143,1085,1355424227),(859259,1046,1355843116),(859267,1046,1355813296),(859276,1045,1357860647),(859458,1085,1355175489),(859679,1085,1355248550),(859848,1045,1357933504),(859978,1046,1357336021),(860051,1046,1356107453),(860111,1045,1357320224),(860277,1045,1355542492),(860466,1046,1355176339),(861206,1045,1355246527),(861258,1045,1357346873),(861281,1045,1357091348),(861522,1046,1355876444),(861667,1046,1357336998),(861747,1045,1355542987),(861832,1085,1355455110),(861883,1046,1355940872),(862377,1046,1357337533),(862534,1046,1357326127),(862608,1085,1355240147),(862662,1045,1358077153),(862662,1046,1358077185),(862768,1085,1355257788),(862916,1045,1358121074),(862953,1045,1358010546),(862967,1046,1357835407),(863170,1046,1355856086),(863199,1046,1357336342),(863628,1046,1355830448),(863631,1045,1356524422),(863694,15095,1356732457),(863770,1046,1355838879),(863781,1046,1355847454),(863870,1045,1355515661),(863959,1045,1357774485),(863959,1236,1356121096),(864056,1045,1355819194),(864066,1045,1355515750),(864066,1085,1355241098),(864215,1045,1357950745),(864335,1046,1355850024),(864366,1045,1356128833),(864458,1085,1355271057),(864479,1045,1357926177),(864533,1085,1355259085),(864699,1045,1355239049),(864699,1085,1355239035),(864717,1236,1356029666),(864721,1085,1355251444),(864760,1045,1356144371),(864808,1046,1356196975),(864846,1046,1355814673),(864919,1085,1355322622),(864970,1085,1355240907),(865000,1045,1357585907),(865043,1045,1355858977),(865043,1236,1356375821),(865067,1045,1356128823),(865179,1045,1357403327),(865209,1045,1357390092),(865243,1046,1356007988),(865253,1045,1355781691),(865295,1046,1355948341),(865425,1045,1357534594),(865498,1046,1355838311),(865573,1045,1357766780),(865584,1045,1357842887),(865755,1045,1357824820),(865767,1085,1355248976),(865836,1045,1355507919),(865991,1085,1355253994),(866011,1045,1357767769),(866137,1085,1355240588),(866338,1046,1355845300),(866908,1046,1357336805),(867196,1045,1355524096),(867463,1046,1356229273),(867948,1046,1357584542),(868590,1045,1357812851),(868590,1046,1357811569),(868690,1046,1355846026),(869009,1085,1355255417),(869138,1046,1355866305),(869191,1046,1355842251),(869465,1046,1355834667),(869768,1045,1357693480),(869770,1046,1355586960),(870211,1046,1356049747),(870288,1085,1355285527),(870320,1046,1355860418),(870352,1046,1355864673),(870412,1085,1355248931),(870575,1046,1356102079),(870847,1045,1357387795),(870855,1045,1355819737),(870855,1046,1355819173),(870940,1085,1355243487),(870947,1085,1355184561),(871043,1085,1355261156),(871079,1046,1355864347),(871278,1085,1355273401),(871334,1045,1357324518),(871334,1227,1357324515),(871334,1236,1357324466),(871417,1046,1357341103),(871433,1046,1357337719),(871610,1045,1357411300),(871771,1046,1355953191),(872034,1046,1355808558),(872046,1045,1357934224),(872130,1045,1357932838),(872377,1046,1356599143),(872377,1085,1355212961),(872512,1085,1355236153),(872674,1046,1357324087),(872678,1045,1355503007),(872905,1046,1355809708),(872929,1046,1355887870),(872931,1085,1355244073),(872965,1085,1355242349),(872993,1046,1355970984),(873018,1045,1355605951),(873246,1085,1355458524),(873374,1045,1356144856),(873378,1046,1355827950),(873420,1045,1357328042),(873451,1046,1356148435),(873621,1046,1355831479),(873661,1046,1355854303),(874161,1045,1357403862),(874288,1085,1355237300),(874431,1046,1355831382),(874443,1085,1355236274),(874665,1085,1355435587),(874672,1046,1355831173),(874836,1046,1355849370),(874848,15077,1356383383),(875088,1046,1355807779),(875288,1045,1357369315),(875595,1046,1355852362),(875695,1045,1355507225),(875966,1045,1357351431),(876039,1046,1355811016),(876112,1046,1355808006),(876237,1045,1357947133),(876542,1085,1355254454),(876760,1045,1357493425),(876938,1085,1355264194),(876990,1046,1355831549),(877245,1046,1355847415),(877249,1045,1355531228),(877431,1046,1356019849),(877537,1046,1355858306),(877619,1046,1356019809),(877726,1046,1355878440),(877811,1085,1355246352),(877827,1045,1357939830),(877834,1045,1357405598),(877834,1236,1357405511),(877874,1085,1355506064),(878188,1085,1355243732),(878210,1045,1357763104),(878485,1046,1355838261),(878502,1045,1355507237),(878696,1085,1355243425),(878711,1045,1355605675),(878743,1045,1357932233),(878751,1045,1357964774),(878768,1085,1355244787),(878788,1045,1357327664),(878837,1085,1355244243),(878933,1085,1355358183),(878946,1045,1356140998),(878979,1045,1357957286),(879319,1046,1357337617),(879376,1085,1355261701),(879408,1045,1355345170),(879632,1045,1357408294),(879793,1045,1357267422),(879834,1046,1355836831),(879846,1085,1355236438),(879865,1085,1355270067),(879873,1085,1355320203),(879935,1046,1355842560),(879963,1085,1355237686),(879968,1085,1355236055),(880014,1085,1355237749),(880051,1085,1355235843),(880064,1046,1355814990),(880064,1085,1355235545),(880148,1085,1355253747),(880219,1046,1355838870),(880219,1085,1355238512),(880255,1045,1357939259),(880255,1046,1355837491),(880255,11949,1357938932),(880260,1045,1355244099),(880260,1085,1355244079),(880390,1085,1355236741),(880407,1045,1355516122),(880407,1085,1355235277),(880419,1045,1355347306),(880423,1085,1355237601),(880456,1045,1356123143),(880478,1085,1355239604),(880515,1085,1355237636),(880519,1085,1355284930),(880529,1085,1355260547),(880632,1085,1355236838),(880655,1085,1355277968),(880779,1085,1355237786),(880828,1045,1355523165),(880847,1085,1355236546),(880869,1085,1355243324),(880916,1046,1355839790),(880955,1046,1355936065),(880989,1085,1355257436),(881010,1046,1355860686),(881036,1085,1355239681),(881039,1045,1355535010),(881063,1085,1355241186),(881136,1085,1355274157),(881276,1085,1355257528),(881342,1085,1355236841),(881358,1085,1355237091),(881399,1045,1356100402),(881536,1085,1355271472),(881545,1085,1355236236),(881582,1085,1355238934),(881594,1085,1355282383),(881605,1085,1355235366),(881618,1085,1355279200),(881807,1085,1355247533),(881873,1045,1357327977),(881930,1085,1355254259),(881940,1085,1355245373),(881943,1046,1355841069),(881977,1085,1355237855),(881978,1085,1355249524),(881991,1085,1355240214),(882025,1085,1355237168),(882035,1085,1355242401),(882160,1085,1355249030),(882172,1085,1355239717),(882200,1085,1355316520),(882225,1046,1355834036),(882231,1045,1355535887),(882418,1085,1355338669),(882525,1085,1355274121),(882545,1085,1355240247),(882566,1045,1355510136),(882578,1085,1355244702),(882596,1085,1355413425),(882623,1046,1355847565),(882664,1046,1355810577),(882669,1045,1355686208),(882711,1085,1355240428),(882719,14,1356042845),(882726,1085,1355271019),(882774,1046,1355868573),(882825,1085,1355257871),(882836,1046,1355808115),(882845,1085,1355236283),(882912,1045,1355584299),(882935,1085,1355242695),(882971,1045,1357512214),(882984,1085,1355347373),(883043,1085,1355243397),(883168,1046,1355846490),(883176,1046,1355834578),(883213,1046,1355844516),(883250,1085,1355329720),(883504,1085,1355328875),(883541,1046,1355845378),(883541,1085,1355244549),(883578,1085,1355237648),(883597,1045,1356119815),(883622,1046,1355848711),(883670,1085,1355247344),(883737,1045,1357476381),(883776,1085,1355258367),(883790,1085,1355239755),(883852,1085,1355242320),(883870,1046,1355839603),(883887,1085,1355244887),(883911,1046,1355807518),(883916,1085,1355269032),(883926,1046,1355835055),(883943,1085,1355330420),(884098,1085,1355340888),(884106,1045,1355505391),(884152,1045,1355630675),(884152,1085,1355250363),(884189,1085,1355240772),(884208,1085,1355237431),(884239,1085,1355312856),(884308,1085,1355249843),(884358,1085,1355256531),(884393,1085,1355239416),(884396,1045,1357325367),(884423,1046,1355842825),(884423,1085,1355259645),(884443,1046,1355864127),(884467,1085,1355244275),(884493,1045,1357360037),(884523,1085,1355244883),(884524,1085,1355269703),(884555,1085,1355255728),(884580,1045,1357620074),(884580,1046,1356583959),(884611,1046,1355854453),(884700,1045,1355885946),(884741,1045,1356121516),(884743,1046,1355829176),(884786,1085,1355277679),(884813,1046,1355841474),(884884,1046,1355854798),(884919,1085,1355314543),(884923,1046,1355844657),(884941,1085,1355242716),(884965,1046,1355843496),(884997,1046,1355835794),(885014,1085,1355285138),(885049,1085,1355264955),(885056,1085,1355264711),(885123,1085,1355266827),(885172,1046,1355870289),(885182,1085,1355260551),(885183,1085,1355318149),(885188,1046,1355876770),(885194,1085,1355278586),(885354,1085,1355256975),(885395,1085,1355272540),(885419,1085,1355237841),(885471,1046,1356058928),(885498,1045,1357329466),(885501,1085,1355278132),(885533,1046,1355940455),(885552,1085,1355246143),(885560,1085,1355246472),(885580,1046,1355833867),(885647,1085,1355236311),(885655,1085,1355243258),(885664,1085,1355243799),(885672,1085,1355244903),(885682,1046,1355276804),(885753,14,1355377287),(885776,1042,1357341179),(885776,1046,1357341181),(885845,1085,1355240115),(885871,1046,1355849366),(885875,1085,1355352438),(885904,1046,1355812297),(885956,1046,1355810202),(885987,1046,1355888686),(885992,1085,1355289858),(886039,1046,1355807223),(886041,1046,1355810220),(886087,1046,1355939541),(886092,1045,1357953578),(886100,1045,1357327734),(886124,1085,1355320043),(886159,1085,1355319127),(886247,1046,1355846378),(886349,1085,1355237758),(886413,1046,1355884781),(886416,1085,1355259481),(886546,1046,1355809163),(886558,1045,1357331516),(886564,1046,1355816862),(886564,1085,1355328514),(886576,1085,1355245173),(886585,1045,1358030700),(886618,1085,1355265197),(886623,1045,1357347839),(886738,1045,1357366294),(886774,1236,1357448041),(886785,1085,1355321960),(886884,1045,1357883422),(886904,1045,1358003084),(887130,1045,1357225765),(887237,1046,1355838325),(887268,1085,1355272433),(887377,1046,1355829168),(887379,1085,1355289984),(887390,1085,1355238176),(887409,1046,1355856073),(887425,1085,1355273908),(887431,1045,1358016155),(887431,1046,1358016217),(887465,1085,1355356652),(887553,1045,1357311409),(888389,1085,1355247752),(888942,1085,1355238204),(889018,1045,1356128394),(889147,1045,1357334030),(889447,1046,1355858191),(889737,1045,1356122063),(889737,1085,1355236134),(889983,1046,1355813638),(889987,1046,1355836847),(889990,1046,1357337054),(890129,1046,1357324152),(890132,1085,1355249481),(890214,1045,1357938561),(890336,1045,1357328459),(890562,1085,1355239810),(890628,1085,1355240494),(890732,1045,1355507920),(890736,1046,1355808565),(890818,1045,1356122465),(890818,1046,1355867579),(890822,1045,1355585114),(890840,1046,1355835313),(890841,1085,1355270033),(891027,1046,1355852440),(891070,1046,1355848772),(891127,1046,1355809119),(891143,1046,1355850022),(891157,1046,1355828885),(891190,1046,1356008472),(891227,1046,1355847724),(891259,1046,1357100035),(891299,1046,1355840564),(891308,1046,1355831632),(891384,1045,1355867801),(891436,1085,1355237348),(891467,1046,1355845515),(891544,1046,1355835555),(891570,1046,1355828866),(891739,1046,1355361005),(891788,1046,1355839028),(892125,1085,1355200222),(892155,1085,1355283832),(892188,1045,1357946491),(892203,1046,1355806187),(892236,1045,1357365838),(892368,1045,1355527517),(892417,1046,1355845426),(892464,1085,1355243456),(892496,1046,1355874933),(892587,1045,1357348049),(892598,1045,1358013313),(892621,1085,1355279397),(892804,1085,1355290989),(892941,1046,1355813521),(893016,1085,1355245969),(893030,1046,1355808231),(893043,1045,1356122665),(893321,1046,1357322983),(893385,1046,1355837079),(893439,1046,1355854345),(893449,1046,1355838899),(893463,1046,1357339045),(893470,1046,1355809393),(893491,1046,1355844103),(893554,1046,1355842162),(893557,1046,1357934657),(893591,1046,1355831296),(893814,1046,1355846092),(893866,1045,1357327758),(893871,1046,1355838745),(894147,1236,1355858085),(894194,1046,1356376487),(894329,1046,1355844474),(894553,1046,1355814632),(894561,1046,1355819006),(894564,1085,1355267712),(894664,1046,1355966567),(894715,1046,1356556325),(894813,1045,1357353184),(895090,1046,1355834607),(895286,1045,1355348368),(895369,1045,1357327400),(895481,1045,1357956995),(895517,1046,1355886067),(895717,1085,1355240537),(895754,1085,1355339363),(895765,1046,1355838061),(895855,1046,1355839353),(895987,1046,1355891024),(896161,1046,1356029931),(896231,1046,1355518718),(896345,1045,1357937773),(896425,1046,1355859630),(896444,1046,1355861059),(896462,1085,1355348845),(896692,1085,1355268555),(896721,1046,1355838818),(896771,1046,1355861226),(896793,1046,1356107272),(897001,1046,1355849286),(897174,1045,1355859367),(897209,1046,1355875901),(897212,1045,1357942039),(897391,1046,1355845107),(897453,1046,1355865655),(897534,1045,1357592122),(897815,1045,1358014260),(897882,1046,1355812359),(897922,1045,1356128869),(898108,1046,1355835937),(898173,1046,1356031011),(898215,1046,1355851058),(898355,1045,1357365686),(898509,1046,1355932202),(898536,1046,1355890712),(898571,1046,1356359114),(898583,1085,1355273875),(898654,1046,1355844569),(898694,1045,1358036158),(898780,1046,1357338288),(899008,1045,1357402442),(899115,1046,1355942004),(899161,1046,1357338153),(899486,1045,1357951800),(899575,1045,1356207297),(899575,1046,1356037090),(899632,1085,1355503266),(899690,1045,1355859563),(899741,1085,1355359840),(899934,1046,1355843293),(899946,1085,1355263906),(899949,1085,1355247450),(900011,1046,1357339342),(900138,1046,1357321201),(900143,1045,1355351057),(900199,1045,1358011263),(900254,1046,1356042880),(900325,1045,1355694483),(900411,1045,1356135585),(900537,1046,1355862352),(900553,1045,1357956208),(900837,1085,1355248643),(901166,1046,1355836177),(901270,1046,1355833466),(901338,1085,1355292675),(901365,1046,1355828117),(901416,1045,1357439674),(901775,1085,1355251202),(901915,1046,1355839145),(901964,1045,1355522964),(902097,1046,1355970161),(902144,1046,1355809734),(902173,1046,1357336487),(902208,1045,1356157261),(902234,1046,1355867825),(902303,1046,1355840715),(902329,1045,1357400301),(902360,1045,1357350178),(902491,1045,1356372449),(902529,1046,1355840158),(902673,1046,1355849281),(902685,1046,1357932680),(902728,1045,1355188395),(902728,1085,1355188375),(902848,1046,1357336531),(903046,1046,1355856839),(903146,1046,1355864584),(903153,1046,1355841004),(903224,1046,1355846928),(903312,1045,1357417941),(903404,1045,1357337215),(903404,1046,1357337211),(903415,1046,1355809497),(903459,1045,1357410235),(903462,1046,1355841442),(903505,1085,1355252224),(903650,1085,1355236405),(903774,1046,1355837084),(903821,1085,1355246292),(904069,1045,1357763321),(904304,1045,1355362034),(904340,1045,1356286555),(904420,1046,1355811991),(904420,1085,1355350944),(904433,1045,1355527738),(904665,1046,1355836895),(904813,1046,1355813705),(904818,1045,1358034892),(904818,1046,1355805921),(904829,1046,1355839079),(904905,1046,1355856863),(904963,1046,1355809362),(905027,1046,1355926539),(905127,1046,1355853135),(905289,1046,1355811641),(905296,1045,1357969781),(905329,1085,1355283418),(905350,1045,1357436326),(905413,1046,1355940221),(905517,1085,1355236433),(905808,1045,1358036373),(905822,1046,1355807987),(905869,1046,1355815755),(905961,1085,1355255386),(906045,1046,1355822638),(906123,1046,1355808580),(906143,1045,1355505503),(906209,1045,1357961256),(906221,1046,1355830146),(906419,1045,1357327133),(906570,1046,1355846747),(906702,1046,1355847590),(906704,1085,1355508515),(906717,14,1357943125),(906745,1085,1355424635),(906746,1046,1355838004),(906761,1046,1355932381),(906968,1046,1355841735),(907053,1085,1355238531),(907146,1045,1358026516),(907256,1085,1355242392),(907285,1045,1356179253),(907296,1046,1357309708),(907402,1045,1356121507),(907402,1046,1355835731),(907410,1046,1355845725),(907484,1046,1355921132),(907502,1085,1355238079),(907570,1046,1355932947),(907588,1046,1357152954),(907638,1085,1355248687),(907822,1085,1355238920),(907834,1046,1355849508),(908098,1045,1355841654),(908100,1046,1355806979),(908142,1085,1355236886),(908265,1085,1355321654),(908436,1045,1357405709),(908483,1046,1355847642),(908519,1045,1357353512),(908535,1085,1355273865),(908563,1046,1355964057),(908622,1046,1355868612),(908634,1046,1355869917),(908704,1045,1355527671),(908707,1046,1355854756),(908714,1045,1355509399),(908748,1046,1355959108),(908830,1046,1356740872),(908837,1085,1355236856),(908841,1046,1355953881),(908845,1045,1356124438),(908907,1046,1355869863),(908968,1045,1357350867),(909014,1045,1355519991),(909071,1046,1355851811),(909146,1085,1355235522),(909149,1236,1355583684),(909160,1046,1355516013),(909181,1045,1355512767),(909227,1046,1355863625),(909227,1085,1355254179),(909228,1085,1355174851),(909250,1045,1355971689),(909295,1046,1355867356),(909389,1045,1357335510),(909400,1046,1355818310),(909480,1045,1357939118),(909488,1045,1356816388),(909506,1045,1358004884),(909553,1046,1355953462),(909605,1046,1356005506),(909773,1046,1355837261),(909799,1045,1356176994),(909799,1046,1355839261),(909836,1045,1355584741),(909885,1045,1357959292),(909885,1046,1355846952),(909921,1085,1355245716),(909930,1085,1355416577),(909967,1046,1356544445),(910171,1045,1357950589),(910194,1046,1355854038),(910219,1085,1355286733),(910223,1045,1357948254),(910223,1046,1355824907),(910233,1046,1356057647),(910240,1046,1357340682),(910273,1045,1357335600),(910312,1085,1355249578),(910355,1045,1357385234),(910355,1046,1355832261),(910360,1046,1355841888),(910376,1046,1355836522),(910397,1046,1355858124),(910421,1046,1355850156),(910462,1045,1355845683),(910464,1085,1355248166),(910478,1045,1357406079),(910671,1085,1355281773),(910689,1085,1355286576),(910691,1085,1355238246),(910732,1085,1355281519),(910735,1046,1355840549),(910756,1085,1355273207),(910779,1085,1355236231),(910803,1085,1355236835),(910815,1045,1355834978),(910820,1046,1357934400),(910820,1085,1355237808),(910851,1085,1355237149),(910876,1085,1355239474),(910890,1085,1355236795),(910932,1085,1355241486),(910961,1046,1355805975),(910985,1085,1355235451),(911002,1045,1357385283),(911017,1085,1355315777),(911045,1085,1355263463),(911053,1045,1355250517),(911053,1085,1355246190),(911053,1227,1355250516),(911137,1085,1355238423),(911140,1046,1355841437),(911153,1085,1355235878),(911161,1085,1355325577),(911164,1085,1355236322),(911205,1085,1355256784),(911212,1085,1355246681),(911264,1046,1355826828),(911328,1046,1357323780),(911341,1085,1355258224),(911360,1085,1355236989),(911386,1046,1355241181),(911386,1085,1355241211),(911418,1046,1357336194),(911477,1045,1357933625),(911487,1085,1355249232),(911505,1046,1355844789),(911561,1046,1355841474),(911579,1085,1355237869),(911596,1085,1355272758),(911629,1085,1355239930),(911632,1085,1355240529),(911651,1046,1355848971),(911657,1085,1355282617),(911680,1085,1355253841),(911688,1085,1355337297),(911693,1046,1355839989),(911701,1085,1355243392),(911740,1085,1355237900),(911742,1046,1357336325),(911770,1085,1355239818),(911800,1045,1355243702),(911800,1085,1355243685),(911873,1085,1355236360),(911882,1085,1355264490),(911981,1045,1357331332),(912048,1085,1355287926),(912189,1085,1355252230),(912206,1085,1355250292),(912266,1045,1355770766),(912266,1046,1355857498),(912275,1085,1355417100),(912388,1085,1355256870),(912397,1085,1355238789),(912400,1085,1355254447),(912542,1046,1355837863),(912569,1085,1355287400),(912580,1045,1357844590),(912909,1085,1355328395),(912927,1045,1355626199),(913290,1045,1355808301),(913298,1085,1355282592),(913490,1045,1357328053),(914100,1045,1357940072),(914156,1085,1355268745),(914220,1046,1355819661),(914231,1085,1355272303),(914637,1045,1358015388),(914780,1085,1355358025),(914949,1085,1355350198),(915020,1085,1355247644),(915381,1045,1355856201),(915932,1085,1355235146),(916292,1085,1355456585),(916580,1085,1355270661),(916591,1046,1355887755),(916628,1046,1355659491),(917365,1236,1355828057),(918312,1046,1355839985),(918980,1046,1355849088),(920152,1085,1355243132),(920579,1045,1355867736),(921413,1046,1355840025),(921530,1045,1355807507),(921924,1045,1357937517),(922525,1045,1355843278),(922708,1046,1355847308),(923007,1046,1355807435),(923733,1045,1355830751),(924266,1236,1356112935),(924336,1085,1355266416),(924426,1045,1355843785),(924465,1046,1355827075),(925053,1046,1355863074),(925287,1046,1357339826),(925593,1236,1355838548),(925941,1085,1355273407),(926401,1085,1355261606),(926646,1085,1355336448),(926652,1085,1355236501),(926884,1085,1355259711),(926969,1045,1357951580),(926983,1085,1355243514),(926986,1045,1355843880),(926986,1046,1355843670),(927155,1046,1355836120),(927225,1085,1355238046),(927607,1045,1355852813),(927743,1046,1355840404),(927849,1046,1357336040),(927849,1236,1355857130),(927856,1046,1355864446),(927896,1085,1355244275),(928233,1045,1357369041),(928460,1085,1355275532),(928620,1085,1355266535),(928859,1046,1357336216),(928920,1085,1355266080),(930872,1085,1355187996),(931415,1046,1355837766),(931603,1046,1355833558),(931604,1085,1355235988),(931996,1046,1355887758),(933021,1046,1355982278),(933027,1085,1355239270),(933318,1045,1355852593),(933318,1046,1355850601),(933318,1227,1355852580),(933318,1236,1355852785),(934081,1046,1355847919),(934378,1236,1356129890),(935726,1046,1355812178),(935755,1046,1355894535),(935976,1085,1355235537),(936294,1045,1355849759),(937333,1046,1355841833),(937734,1045,1357959107),(938504,1046,1355848667),(938570,1045,1355835405),(938578,1045,1357011433),(938631,1046,1355497334),(938711,1046,1355844907),(938793,1046,1355807540),(938966,1045,1357935504),(939007,1046,1356120199),(939423,1045,1355807745),(939609,1045,1357554655),(939609,1227,1357554649),(939609,1236,1357554608),(939949,1045,1355859044),(939949,1227,1355859043),(940018,1236,1357325468),(940135,1085,1355314291),(940252,1045,1357869885),(940380,1046,1355836014),(940420,1046,1355858037),(941630,1085,1355236486),(941861,1046,1357341538),(941879,1046,1355847242),(941940,1085,1355193248),(942292,1046,1355898185),(942424,1236,1357334136),(942822,1046,1355838138),(943337,1046,1355840172),(943825,1045,1355848859),(944891,1046,1357338140),(944913,1046,1356029140),(945233,1040,1357938203),(945233,1042,1357938114),(945233,1045,1357938204),(945589,1040,1357594694),(945589,1045,1357594696),(945597,1236,1357431016),(945619,1045,1357335553),(945619,1046,1355808921),(945748,1085,1355264948),(945765,11937,1357935567),(945894,1085,1355238829),(945899,1085,1355279546),(945935,1046,1355838646),(946026,1046,1355833997),(946148,1045,1357326133),(946580,1085,1355239417),(946598,1045,1355839522),(946616,1085,1355238358),(946704,1085,1355238556),(946847,1085,1355245548),(946866,1046,1355845133),(946960,1046,1356033332),(947225,1236,1355253862),(947225,11937,1355253531),(947449,1085,1355241816),(947538,1045,1357269709),(947538,1236,1357269659),(947552,1046,1355847415),(947639,1045,1357345160),(947639,1046,1357345131),(947704,1085,1355284757),(947757,1085,1355276421),(947818,1046,1355583804),(947932,1046,1355839823),(947963,1085,1355250381),(948060,1085,1355243430),(948119,1085,1355247440),(948596,1046,1355861438),(948742,1046,1355823310),(948765,1085,1355237248),(948768,1085,1355250600),(948848,1085,1355312141),(948887,1085,1355246624),(948924,1046,1355844746),(949045,1045,1357584473),(949144,1045,1355869717),(949215,1085,1355237418),(949283,1046,1356083360),(949658,1046,1355843012),(949759,1085,1355255461),(949936,1085,1355248027),(949944,1046,1356011881),(950217,1085,1355288508),(950257,1085,1355281253),(950324,1045,1355885057),(950374,1085,1355264610),(950406,1046,1355275046),(950707,1046,1355879705),(950958,1045,1357960158),(950958,1085,1355272670),(950967,1046,1355880933),(951298,1046,1355861968),(951336,1046,1358093570),(951429,1085,1355276064),(951480,1085,1355241457),(952010,1045,1357328010),(952212,1085,1355237938),(953157,1236,1357744552),(953677,1236,1355831121),(953883,1045,1357983952),(954483,1045,1357326694),(954488,1046,1355849542),(955084,1085,1355280126),(955189,1046,1355835476),(956407,1046,1357938235),(956432,1085,1355287829),(957446,1046,1355840818),(958476,1045,1357988026),(958618,1045,1355348076),(959025,1045,1355847012),(959500,1046,1355808052),(959702,1085,1355238394),(959749,1046,1355841826),(960519,1236,1356923710),(960748,1045,1355840866),(961051,1085,1355290428),(961622,1085,1355372471),(962014,1045,1357778979),(962014,1085,1355332718),(962043,1046,1355811756),(962234,1085,1355249330),(963181,1085,1355433965),(963467,1046,1355808962),(964066,1045,1357952374),(964331,1046,1355832294),(964776,1085,1355245643),(965214,1046,1356065002),(965615,1046,1355839451),(965803,1046,1357334853),(965803,1236,1357334936),(966365,1046,1357326597),(966796,1046,1355927807),(967174,1046,1355866979),(967617,1046,1357935106),(967668,1045,1355835379),(968216,1085,1355248486),(968537,1045,1355827665),(968539,1085,1355416182),(969086,1046,1355975498),(969249,1046,1357326799),(969249,1236,1357326684),(969933,1040,1355918010),(969933,1045,1355918012),(969995,1046,1355836183),(970277,1046,1355862201),(970536,1046,1355961542),(970774,1045,1355514435),(970866,1045,1357952831),(971538,1046,1355485700),(971620,1045,1356142518),(971732,1046,1355809072),(971950,1045,1357962824),(971950,1046,1357340295),(972066,1046,1356053233),(972104,1236,1358020653),(972224,1046,1355970852),(972776,1045,1357372219),(972849,1085,1355262504),(972860,1046,1355821098),(972862,1046,1357109042),(973152,1046,1355935407),(974151,1046,1357336082),(974440,1045,1357389237),(974440,1236,1355841901),(974463,1046,1355850248),(974535,1236,1357343892),(974985,1085,1355329786),(975068,1085,1355362663),(975106,1045,1357934518),(975786,1046,1357334658),(975786,1085,1355262733),(975807,1046,1355856599),(975889,1085,1355279781),(975905,1046,1357340362),(975920,1045,1355363032),(975939,1046,1357341489),(975958,1046,1357132292),(976048,1046,1357255113),(976193,1045,1358002927),(976216,1046,1355845225),(976294,1046,1355867382),(976460,1046,1355842807),(976460,1236,1355843424),(976578,1046,1355852616),(976642,1045,1355871437),(976651,1085,1355244025),(976762,1045,1355881584),(976814,1045,1355935136),(976872,1045,1357592026),(977076,1046,1355988168),(977151,1045,1355435908),(977153,1046,1355656984),(977182,1045,1357543446),(977182,1046,1358154586),(977182,1227,1356161950),(977182,15033,1355817470),(977217,1045,1355854375),(977536,1085,1355200659),(978129,1046,1355964874),(978397,1046,1355837862),(978407,1085,1355241035),(978531,1045,1355539144),(978531,1085,1355348841),(978712,1085,1355257211),(978808,1046,1355359634),(978896,1045,1355870136),(978896,1046,1355870024),(979019,1085,1355238963),(979267,1046,1357340513),(979666,1046,1355869867),(979666,1236,1357154333),(979722,1085,1355266045),(979895,1045,1355891057),(980267,1045,1355876536),(980312,1046,1355808517),(980330,1046,1355837182),(980429,1046,1356305105),(980543,1046,1355851404),(980604,1046,1355846708),(980861,1236,1357330394),(980897,1085,1355353074),(980945,1046,1357965044),(981557,1046,1355915155),(982216,1085,1355274258),(982216,1236,1355810655),(982258,1046,1355846979),(982822,1046,1355840310),(983259,1046,1355846324),(983304,1046,1355825605),(983375,1045,1355843375),(983733,1085,1355436899),(984942,1046,1357336075),(985001,1045,1355872036),(985333,1045,1355816872),(985423,1085,1355247370),(985429,1085,1355240302),(985437,1046,1355196912),(985453,1045,1357073030),(985453,1085,1355174900),(985454,1085,1355175059),(985455,1085,1355175386),(985456,1085,1355175662),(985457,1085,1355176318),(985458,1085,1355176606),(985459,1085,1355176754),(985460,1085,1355176899),(985461,1085,1355177242),(985462,1085,1355177971),(985463,1085,1355177992),(985465,1085,1355178779),(985466,1085,1355179118),(985467,1085,1355179278),(985468,1085,1355179944),(985469,1045,1355180261),(985469,1085,1355180248),(985470,1085,1355180309),(985471,1085,1355180854),(985472,1085,1355181403),(985473,1085,1355181956),(985474,1085,1355182104),(985475,1085,1355182226),(985476,1085,1355182777),(985477,1085,1355183132),(985478,1085,1355184066),(985479,1085,1355184618),(985480,1085,1355184868),(985481,1085,1355185007),(985482,1085,1355185250),(985483,1085,1355185277),(985484,1085,1355185469),(985485,1085,1355186161),(985486,1085,1355188879),(985487,1085,1355190862),(985488,1085,1355191841),(985489,1085,1355192149),(985490,1085,1355193461),(985491,1085,1355194241),(985492,1085,1355194421),(985493,1085,1355194543),(985494,1085,1355195527),(985495,1085,1355196215),(985496,1085,1355237648),(985497,1085,1355196757),(985498,1085,1355197468),(985499,1085,1355198300),(985500,1085,1355198791),(985502,1046,1356796375),(985502,1085,1355200792),(985503,1085,1355201472),(985505,1085,1355203855),(985506,1085,1355205036),(985507,1085,1355206238),(985508,1085,1355208219),(985509,1085,1355209418),(985510,1085,1355211596),(985511,1085,1355211962),(985512,1085,1355224145),(985513,1085,1355224424),(985514,1085,1355224931),(985515,1085,1355231966),(985516,1085,1355232975),(985517,1085,1355233418),(985518,1085,1355234656),(985519,1085,1355234771),(985520,1085,1355234888),(985521,1085,1355234892),(985522,1085,1355234912),(985523,1085,1355234941),(985524,1085,1355234958),(985525,1085,1355234974),(985526,1085,1355234999),(985527,1085,1355235096),(985528,1085,1355235101),(985529,1085,1355235119),(985530,1085,1355235125),(985531,1085,1355235139),(985532,1085,1355235148),(985533,1085,1355235151),(985534,1085,1355235161),(985535,1085,1355235200),(985536,1085,1355235218),(985537,1085,1355235234),(985538,1085,1355235237),(985539,1085,1355235237),(985540,1085,1355235251),(985541,1085,1355235258),(985542,1085,1355235280),(985543,1085,1355235304),(985544,1085,1355235312),(985545,1085,1355235315),(985546,1085,1355235316),(985547,1085,1355235323),(985548,1085,1355235382),(985549,1085,1355235342),(985550,1085,1355235376),(985551,1085,1355235361),(985552,1085,1355235363),(985553,1085,1355235379),(985554,1085,1355235383),(985555,1085,1355235389),(985557,1085,1355235398),(985558,1085,1355235400),(985559,1085,1355235401),(985560,1046,1355235594),(985560,1085,1355235404),(985561,1085,1355235418),(985562,1085,1355235441),(985563,1085,1355235479),(985564,1085,1355235480),(985565,1085,1355333238),(985566,1085,1355235495),(985567,1085,1355235501),(985568,1085,1355235502),(985569,1085,1355235522),(985570,1085,1355235526),(985571,1085,1355235527),(985572,1085,1355235528),(985573,1085,1355235539),(985574,1085,1355235548),(985575,1085,1355235552),(985576,1085,1355235555),(985577,1085,1355235557),(985578,1085,1355235569),(985579,1085,1355235570),(985580,1085,1355235575),(985581,1085,1355235584),(985582,1085,1355235597),(985583,1085,1355235636),(985584,1085,1355278588),(985585,1085,1355235619),(985586,1085,1355235622),(985587,1085,1355235636),(985588,1085,1355235639),(985589,1085,1355235640),(985590,1085,1355235641),(985591,1085,1355235643),(985592,1085,1355235644),(985593,1085,1355235645),(985594,1085,1355235652),(985595,1085,1355235663),(985596,1085,1355235664),(985597,1085,1355235664),(985598,1085,1355235664),(985599,1085,1355235665),(985600,1085,1355235670),(985601,1085,1355235672),(985602,1085,1355235679),(985603,1085,1355235681),(985604,1085,1355235684),(985605,1085,1355235685),(985606,1085,1355235688),(985607,1085,1355235693),(985608,1085,1355235700),(985609,1085,1355235773),(985610,1085,1355235718),(985611,1085,1355235719),(985612,1085,1355235721),(985613,1085,1355235721),(985614,1085,1355235725),(985615,1085,1355235743),(985616,1085,1355235748),(985617,1085,1355235751),(985618,1085,1355235754),(985619,1085,1355235764),(985620,1085,1355235767),(985621,1085,1355235772),(985622,1085,1355235779),(985623,1085,1355235792),(985624,1085,1355235794),(985625,1085,1355235795),(985626,1085,1355235798),(985627,1085,1355235804),(985628,1085,1355235886),(985629,1085,1355235809),(985630,1085,1355235816),(985631,1085,1355235827),(985632,1085,1355235827),(985633,1085,1355235834),(985634,1085,1355235839),(985635,1085,1355235847),(985636,1085,1355235854),(985637,1085,1355235857),(985638,1085,1355235858),(985639,1085,1355235858),(985640,1085,1355235861),(985641,1085,1355235867),(985642,1085,1355235875),(985643,1085,1355237658),(985644,1045,1355235901),(985644,1085,1355235891),(985645,1085,1355235894),(985646,1085,1355235895),(985647,1085,1355235898),(985648,1085,1355235906),(985649,1085,1355235907),(985650,1085,1355235910),(985651,1085,1355235911),(985652,1085,1355239452),(985653,1085,1355235916),(985654,1085,1355236208),(985654,1236,1355236108),(985655,1085,1355235927),(985656,1085,1355235935),(985657,1085,1355235936),(985658,1085,1355235943),(985659,1085,1355235943),(985660,1085,1355235947),(985661,1085,1355235952),(985662,1085,1355235963),(985663,1085,1355235964),(985664,1085,1355235979),(985664,1236,1355237137),(985665,1085,1355235991),(985666,1085,1355235994),(985667,1085,1355236072),(985668,1085,1355236002),(985669,1085,1355236003),(985670,1085,1355236006),(985671,1085,1355236007),(985672,1085,1355236008),(985673,1085,1355236011),(985674,1085,1355236011),(985675,1085,1355236014),(985676,1085,1355236017),(985677,1085,1355236018),(985678,1085,1355236019),(985679,1085,1355236019),(985680,1085,1355236022),(985681,1085,1355236023),(985682,1085,1355236029),(985683,1085,1355236108),(985684,1085,1355236037),(985685,1085,1355236047),(985686,1085,1355236049),(985687,1085,1355236053),(985688,1085,1355236055),(985689,1085,1355236058),(985690,1085,1355236181),(985691,1085,1355236071),(985692,1085,1355236078),(985693,1085,1355236079),(985694,1085,1355236079),(985695,1085,1355236085),(985696,1085,1355236088),(985697,1085,1355236105),(985698,1085,1355236106),(985699,1085,1355236116),(985700,1085,1355236121),(985701,1085,1355236124),(985702,1085,1355236131),(985703,1085,1355236132),(985704,1085,1355236133),(985705,1085,1355236134),(985706,1085,1355236137),(985707,1085,1355236143),(985708,1085,1355236147),(985709,1085,1355236148),(985710,1085,1355236153),(985711,1085,1355236154),(985712,1085,1355236154),(985713,1085,1355236158),(985714,1085,1355236325),(985715,1085,1355236166),(985716,1085,1355236177),(985717,1085,1355236178),(985718,1085,1355236181),(985719,1085,1355236186),(985720,1085,1355236191),(985721,1085,1355236351),(985722,1085,1355236199),(985723,1085,1355242445),(985724,1085,1355236202),(985725,1085,1355236204),(985726,1085,1355236209),(985727,1085,1355236217),(985728,1085,1355236218),(985729,1085,1355236220),(985730,1085,1355236225),(985731,1085,1355236229),(985732,1046,1355236694),(985732,1085,1355236232),(985733,1085,1355236241),(985734,1085,1355236247),(985735,1085,1355236247),(985736,1085,1355236253),(985737,1085,1355236255),(985738,1085,1355236270),(985739,1085,1355236272),(985740,1085,1355236277),(985741,1085,1355236279),(985742,1085,1355236297),(985743,1085,1355236298),(985744,1085,1355236316),(985745,1085,1355236320),(985746,1085,1355236328),(985747,1085,1355236328),(985748,1085,1355236332),(985749,1085,1355236335),(985750,1085,1355236337),(985751,1085,1355236345),(985752,1085,1355236458),(985753,1085,1355236350),(985754,1085,1355236359),(985755,1085,1355236361),(985756,1085,1355236367),(985757,1085,1355236368),(985758,1085,1355236370),(985759,1085,1355236370),(985760,1085,1355323568),(985761,1085,1355236370),(985762,1085,1355236374),(985763,1085,1355236376),(985764,1085,1355236377),(985765,1085,1355236378),(985766,1085,1355236383),(985767,1085,1355236385),(985768,1085,1355236386),(985769,1085,1355236393),(985770,1085,1355236394),(985771,1085,1355236398),(985772,1085,1355236406),(985773,1085,1355236406),(985774,1045,1355237337),(985774,1085,1355236406),(985774,1227,1355237333),(985775,1045,1355236424),(985775,1085,1355236422),(985776,1085,1355236422),(985777,1085,1355236423),(985778,1085,1355236424),(985779,1085,1355236427),(985780,1085,1355236429),(985781,1085,1355236429),(985782,1085,1355236432),(985783,1085,1355236441),(985784,1085,1355236441),(985785,1085,1355236445),(985786,1085,1355236446),(985787,1085,1355236447),(985788,1085,1355236448),(985789,1085,1355236448),(985790,1085,1355236449),(985791,1085,1355236449),(985792,1085,1355236450),(985793,1085,1355236452),(985794,1085,1355236454),(985795,1085,1355236455),(985796,1085,1355236458),(985797,1085,1355236458),(985798,1085,1355237732),(985799,1085,1355236466),(985800,1085,1355236467),(985801,1085,1355236467),(985802,1085,1355236471),(985803,1085,1355236472),(985804,1085,1355242329),(985805,1046,1355816108),(985805,1085,1355236988),(985806,1085,1355236482),(985807,1085,1355236484),(985808,1085,1355236488),(985809,1085,1355236492),(985810,1085,1355270867),(985811,1085,1355236499),(985812,1085,1355236500),(985813,1085,1355236501),(985814,1085,1355236507),(985815,1085,1355236507),(985816,1085,1355236508),(985817,1085,1355236520),(985818,1085,1355236522),(985819,1085,1355236524),(985820,1085,1355236526),(985821,1085,1355236649),(985822,1085,1355236531),(985823,1085,1355236533),(985824,1085,1355236537),(985825,1085,1355236549),(985826,1085,1355236550),(985827,1085,1355236552),(985828,1085,1355236552),(985829,1085,1355236554),(985830,1085,1355236559),(985831,1085,1355236559),(985832,1085,1355236568),(985833,1085,1355236596),(985834,1085,1355236578),(985835,1085,1355236578),(985836,1085,1355236583),(985837,1085,1355236584),(985838,1085,1355236587),(985839,1085,1355236591),(985840,1085,1355236598),(985841,1085,1355236602),(985842,1085,1355236603),(985843,1085,1355236603),(985844,1085,1355236603),(985845,1045,1355510618),(985845,1085,1355236649),(985846,1085,1355236604),(985847,1085,1355236611),(985848,1085,1355236611),(985849,1085,1355236623),(985850,1085,1355236614),(985851,1085,1355236620),(985852,1085,1355236627),(985853,1085,1355236635),(985854,1085,1355236640),(985855,1085,1355236645),(985856,1085,1355236647),(985857,1085,1355236648),(985858,1085,1355236650),(985859,1085,1355236655),(985860,1085,1355236658),(985861,1085,1355236658),(985862,1085,1355236905),(985863,1085,1355236664),(985864,1045,1355237095),(985864,1085,1355236678),(985865,1085,1355236681),(985866,1085,1355236682),(985867,1085,1355236684),(985868,1085,1355236689),(985869,1085,1355236690),(985870,1085,1355236691),(985871,1085,1355236696),(985872,1085,1355236697),(985873,1085,1355236697),(985874,1085,1355236706),(985875,1085,1355236706),(985876,1085,1355236710),(985877,1085,1355236713),(985878,1085,1355236722),(985879,1085,1355236725),(985880,1085,1355236734),(985881,1085,1355236741),(985882,1085,1355236746),(985883,1085,1355236747),(985884,1085,1355236753),(985885,1085,1355236762),(985886,1085,1355236807),(985887,1085,1355236766),(985888,1085,1355236769),(985889,1085,1355236772),(985890,1085,1355236778),(985891,1085,1355236780),(985892,1085,1355236781),(985892,1236,1355236990),(985893,1085,1355236782),(985894,1085,1355236784),(985895,1085,1355236785),(985896,1045,1355238736),(985896,1085,1355236785),(985897,1085,1355236787),(985898,1085,1355236794),(985899,1085,1355236795),(985900,1085,1355236797),(985901,1085,1355236797),(985902,1085,1355236799),(985903,1085,1355236803),(985904,1085,1355236807),(985905,1085,1355236808),(985906,1085,1355236809),(985907,1085,1355236809),(985908,1085,1355236812),(985909,1085,1355252603),(985910,1085,1355236819),(985911,1085,1355236833),(985912,1085,1355236834),(985913,1085,1355236840),(985914,1085,1355236845),(985915,1085,1355236845),(985916,1085,1355236849),(985917,1085,1355237075),(985918,1085,1355236855),(985919,1045,1355237284),(985919,1085,1355236861),(985919,1227,1355237283),(985920,1085,1355236868),(985921,1085,1355236871),(985922,1085,1355236873),(985923,1085,1355236879),(985924,1085,1355236882),(985925,1085,1355236885),(985926,1085,1355236886),(985927,1085,1355236890),(985928,1085,1355236891),(985929,1085,1355236894),(985930,1085,1355236895),(985931,1085,1355236901),(985932,1085,1355236904),(985933,1085,1355236907),(985934,1085,1355236908),(985935,1085,1355236914),(985936,1085,1355236915),(985937,1085,1355236918),(985938,1085,1355236918),(985939,1085,1355236923),(985940,1085,1355236925),(985941,1085,1355236930),(985942,1085,1355236931),(985943,1085,1355236932),(985944,1085,1355236933),(985945,1085,1355236938),(985946,1085,1355236939),(985947,1085,1355236941),(985948,1085,1355236943),(985949,1085,1355236943),(985950,1085,1355236943),(985951,1085,1355236945),(985952,1085,1355236955),(985953,1046,1355812918),(985953,1085,1355236985),(985954,1085,1355236961),(985955,1085,1355237175),(985956,1085,1355236964),(985957,1085,1355236976),(985958,1085,1355236977),(985959,1085,1355236985),(985960,1085,1355236987),(985961,1085,1355236990),(985962,1085,1355236990),(985963,1085,1355236995),(985964,1085,1355236996),(985965,1085,1355237028),(985966,1085,1355237002),(985967,1085,1355237004),(985968,1085,1355237004),(985969,1085,1355237005),(985970,1085,1355237011),(985971,1085,1355237011),(985972,1085,1355237014),(985973,1085,1355237015),(985974,1085,1355237016),(985975,1085,1355237016),(985976,1085,1355237018),(985977,1085,1355237020),(985978,1085,1355237021),(985979,1085,1355237023),(985980,1085,1355237024),(985981,1085,1355237027),(985982,1085,1355237028),(985983,1085,1355237031),(985984,1085,1355237035),(985985,1085,1355237039),(985986,1085,1355237040),(985987,1085,1355237041),(985988,1085,1355237044),(985988,1236,1355237372),(985989,1085,1355237046),(985990,1085,1355237219),(985991,1085,1355237058),(985992,1085,1355237063),(985993,1085,1355237063),(985994,1085,1355237077),(985995,1085,1355237081),(985996,1085,1355237084),(985997,1085,1355237086),(985998,1085,1355237093),(985999,1085,1355237095),(986000,1085,1355237101),(986001,1085,1355237105),(986002,1085,1355237106),(986003,1085,1355237110),(986004,1085,1355237111),(986005,1085,1355237112),(986006,1085,1355237119),(986007,1085,1355237132),(986008,1085,1355237141),(986009,1085,1355237142),(986010,1085,1355237619),(986011,1085,1355237148),(986012,1085,1355237149),(986013,1085,1355237155),(986014,1085,1355237157),(986015,1085,1355237159),(986016,1085,1355238671),(986017,1085,1355237162),(986018,1085,1355237169),(986019,1085,1355237180),(986020,1085,1355237185),(986021,1085,1355237193),(986022,1085,1355237194),(986023,1085,1355237197),(986024,1085,1355237202),(986025,1085,1355237204),(986026,1085,1355237216),(986027,1085,1355237225),(986028,1085,1355237227),(986029,1085,1355237237),(986030,1085,1355237367),(986031,1085,1355237247),(986032,1085,1355237248),(986033,1085,1355237250),(986034,1085,1355237253),(986035,1085,1355237255),(986036,1085,1355237256),(986037,1085,1355237261),(986038,1085,1355237261),(986039,1085,1355237267),(986040,1085,1355237279),(986041,1085,1355237287),(986042,1085,1355237293),(986043,1085,1355237299),(986044,1085,1355237301),(986045,1085,1355237301),(986046,1085,1355237314),(986047,1085,1355237314),(986048,1085,1355237316),(986049,1085,1355237359),(986050,1045,1355237343),(986050,1085,1355237323),(986051,1085,1355237326),(986052,1085,1355237328),(986053,1085,1355237329),(986054,1085,1355237332),(986055,1085,1355237334),(986056,1085,1355237336),(986057,1085,1355237340),(986058,1085,1355237345),(986059,1085,1355237349),(986060,1085,1355237353),(986061,1085,1355237354),(986062,1085,1355237360),(986063,1085,1355237363),(986064,1085,1355237366),(986065,1085,1355237369),(986066,1085,1355237369),(986067,1085,1355237372),(986068,1085,1355237377),(986069,1085,1355237379),(986070,1085,1355237381),(986071,1085,1355237388),(986072,1085,1355237393),(986073,1085,1355237396),(986074,1085,1355237397),(986075,1085,1355237404),(986076,1085,1355237416),(986077,1085,1355237424),(986078,1085,1355237433),(986079,1085,1355237433),(986080,1085,1355237434),(986081,1085,1355237437),(986082,1045,1355237465),(986082,1085,1355237449),(986083,1085,1355237454),(986084,1085,1355237455),(986085,1085,1355237457),(986086,1085,1355237462),(986087,1085,1355237465),(986088,1085,1355237466),(986089,1085,1355237475),(986090,1085,1355237481),(986091,1085,1355237485),(986092,1085,1355237489),(986093,1085,1355237570),(986094,1085,1355237498),(986095,1085,1355237502),(986096,1085,1355237515),(986097,1085,1355237520),(986098,1085,1355237521),(986099,1085,1355237546),(986100,1085,1355237677),(986101,1085,1355237531),(986102,1085,1355237531),(986103,1085,1355237536),(986104,1085,1355237543),(986105,1085,1355237545),(986106,1085,1355237552),(986107,1085,1355237554),(986108,1085,1355237554),(986109,1085,1355237554),(986110,1085,1355237555),(986111,1085,1355237557),(986112,1085,1355237561),(986113,1085,1355237563),(986114,1085,1355237569),(986115,1085,1355237580),(986116,1085,1355237584),(986117,1085,1355237590),(986118,1085,1355237592),(986119,1085,1355237593),(986120,1085,1355238178),(986121,1085,1355237608),(986122,1085,1355237608),(986123,1085,1355237610),(986124,1085,1355237610),(986125,1085,1355237611),(986126,1085,1355237919),(986127,1045,1355237620),(986127,1085,1355237617),(986128,1085,1355237618),(986129,1085,1355237618),(986130,1085,1355237622),(986131,1045,1355238140),(986131,1085,1355237634),(986131,1227,1355238139),(986131,1236,1355238283),(986132,1085,1355237635),(986133,1085,1355237637),(986134,1085,1355237645),(986135,1085,1355237649),(986136,1085,1355237697),(986137,1085,1355237659),(986138,1085,1355237661),(986139,1085,1355237666),(986140,1085,1355237670),(986141,1085,1355237673),(986142,1085,1355237677),(986143,1085,1355237680),(986144,1085,1355237680),(986145,1085,1355237681),(986146,1085,1355237684),(986147,1085,1355237688),(986148,1085,1355237695),(986149,1085,1355237704),(986150,1085,1355237710),(986151,1085,1355237713),(986152,1085,1355237713),(986153,1085,1355237721),(986154,1085,1355238364),(986155,1085,1355237725),(986156,1085,1355237731),(986157,1085,1355237743),(986158,1085,1355237756),(986159,1085,1355237758),(986160,1085,1355237758),(986161,1085,1355237759),(986162,1085,1355237768),(986163,1085,1355237769),(986164,1085,1355237770),(986165,1085,1355237770),(986166,1085,1355237774),(986167,1085,1355237780),(986168,1085,1355237800),(986169,1085,1355237789),(986170,1085,1355237789),(986171,1085,1355237791),(986172,1085,1355237796),(986173,1085,1355237797),(986174,1085,1355237799),(986175,1085,1355237807),(986176,1085,1355237809),(986177,1085,1355237810),(986178,1085,1355237811),(986179,1085,1355237813),(986180,1085,1355237817),(986181,1085,1355237824),(986182,1085,1355237824),(986183,1085,1355237824),(986184,1085,1355238215),(986185,1085,1355237830),(986186,1085,1355237833),(986187,1085,1355237850),(986188,1085,1355237853),(986189,1085,1355237854),(986190,1085,1355237855),(986191,1085,1355237856),(986192,1085,1355237869),(986193,1085,1355237873),(986194,1085,1355237874),(986195,1085,1355244525),(986196,1085,1355237875),(986197,1085,1355237876),(986198,1085,1355237885),(986199,1085,1355238520),(986200,1085,1355237895),(986201,1085,1355237897),(986202,1085,1355237898),(986203,1085,1355237911),(986204,1085,1355237912),(986205,1085,1355269945),(986206,1085,1355237921),(986207,1085,1355237923),(986208,1085,1355237926),(986209,1085,1355237928),(986210,1085,1355237943),(986211,1085,1355237945),(986212,1085,1355237945),(986213,1085,1355237950),(986214,1085,1355237960),(986215,1085,1355237967),(986216,1085,1355237969),(986217,1045,1355237996),(986217,1085,1355237982),(986218,1085,1355237985),(986219,1085,1355237993),(986220,1085,1355238006),(986221,1085,1355238034),(986222,1085,1355238013),(986222,1236,1355238115),(986223,1085,1355238024),(986224,1085,1355238024),(986225,1085,1355238024),(986226,1085,1355238029),(986227,1085,1355238036),(986228,1045,1355248366),(986228,1085,1355238048),(986229,1085,1355238060),(986230,1085,1355238063),(986231,1085,1355238066),(986232,1085,1355238068),(986233,1085,1355238068),(986234,1085,1355238108),(986235,1085,1355238074),(986236,1085,1355238075),(986237,1085,1355238076),(986238,1085,1355238077),(986239,1085,1355238084),(986240,1085,1355238089),(986241,1085,1355238091),(986242,1085,1355238094),(986243,1085,1355238095),(986244,1085,1355238100),(986245,1085,1355238113),(986246,1045,1355238136),(986246,1085,1355238120),(986247,1085,1355238121),(986248,1085,1355238126),(986249,1085,1355238130),(986250,1085,1355238136),(986251,1085,1355238139),(986252,1085,1355238143),(986253,1085,1355238144),(986254,1085,1355238148),(986255,1085,1355238154),(986256,1085,1355238161),(986257,1085,1355238164),(986258,1085,1355238165),(986259,1085,1355238173),(986260,1085,1355238175),(986261,1085,1355238177),(986262,1085,1355238178),(986263,1085,1355238196),(986264,1085,1355238198),(986265,1085,1355238204),(986266,1085,1355238222),(986267,1085,1355238225),(986268,1085,1355238228),(986269,1085,1355238235),(986270,1085,1355238237),(986271,1085,1355238239),(986272,1085,1355238239),(986273,1085,1355238240),(986274,1085,1355238249),(986275,1045,1355238273),(986275,1085,1355238332),(986276,1085,1355238268),(986277,1085,1355238273),(986278,1085,1355238276),(986279,1085,1355238285),(986280,1085,1355238292),(986281,1085,1355238294),(986282,1085,1355238298),(986283,1085,1355238305),(986284,1085,1355238306),(986285,1085,1355238308),(986286,1085,1355238312),(986287,1085,1355238313),(986288,1085,1355238318),(986288,1236,1355238821),(986289,1085,1355238334),(986290,1085,1355238321),(986291,1085,1355238323),(986292,1085,1355238329),(986293,1085,1355238329),(986294,1085,1355238331),(986295,1085,1355238336),(986296,1085,1355238341),(986297,1085,1355238990),(986298,1085,1355238353),(986299,1085,1355238374),(986300,1085,1355238382),(986301,1085,1355238392),(986302,1085,1355238402),(986303,1085,1355238409),(986304,1085,1355238423),(986305,1085,1355238424),(986306,1085,1355238426),(986307,1085,1355238428),(986308,1085,1355238432),(986309,1085,1355238438),(986310,1085,1355238446),(986311,1085,1355238451),(986312,1085,1355238456),(986313,1085,1355238456),(986314,1085,1355238459),(986315,1085,1355238464),(986316,1085,1355238468),(986317,1085,1355238484),(986318,1085,1355238489),(986319,1085,1355238502),(986320,1085,1355238508),(986321,1085,1355238524),(986322,1085,1355238524),(986323,1085,1355238528),(986324,1085,1355238535),(986325,1085,1355238541),(986326,1085,1355238543),(986327,1085,1355238548),(986328,1085,1355238565),(986329,1085,1355238566),(986330,1085,1355238576),(986331,1085,1355238577),(986332,1085,1355238584),(986333,1085,1355238584),(986334,1085,1355238594),(986335,1085,1355238594),(986336,1085,1355238597),(986337,1085,1355238599),(986338,1085,1355238599),(986339,1085,1355238601),(986340,1085,1355238608),(986341,1085,1355238612),(986342,1085,1355238624),(986343,1085,1355278245),(986344,1085,1355238639),(986345,1085,1355238639),(986346,1085,1355238645),(986347,1085,1355238648),(986348,1085,1355238649),(986349,1085,1355238651),(986350,1085,1355238661),(986351,1085,1355238663),(986352,1085,1355238663),(986353,1085,1355238668),(986354,1085,1355238673),(986355,1085,1355238683),(986356,1085,1355238694),(986357,1085,1355238696),(986358,1085,1355238697),(986359,1085,1355238697),(986360,1085,1355238701),(986361,1085,1355238706),(986362,1085,1355238708),(986363,1085,1355238711),(986364,1085,1355238715),(986365,1085,1355238723),(986366,1085,1355238729),(986367,1085,1355238751),(986368,1085,1355238753),(986369,1085,1355238896),(986370,1085,1355238766),(986371,1085,1355238772),(986372,1085,1355238777),(986373,1085,1355238806),(986374,1085,1355238839),(986375,1085,1355238839),(986376,1085,1355238839),(986377,1085,1355238842),(986378,1085,1355238844),(986379,1085,1355238865),(986380,1085,1355239243),(986381,1085,1355238877),(986382,1085,1355238879),(986383,1085,1355238900),(986384,1085,1355238906),(986385,1085,1355238923),(986386,1085,1355238926),(986387,1085,1355238928),(986388,1085,1355238942),(986389,1085,1355238943),(986390,1085,1355238955),(986391,1085,1355239194),(986392,1085,1355238976),(986393,1085,1355238978),(986394,1085,1355238984),(986394,1236,1355239467),(986395,1085,1355238988),(986396,1085,1355238991),(986397,1085,1355238991),(986398,1085,1355238992),(986399,1085,1355238998),(986400,1085,1355239006),(986401,1085,1355239014),(986402,1085,1355239016),(986403,1085,1355239028),(986404,1085,1355239030),(986405,1085,1355239044),(986406,1085,1355239047),(986407,1085,1355239052),(986408,1085,1355239056),(986409,1085,1355239064),(986410,1085,1355239069),(986411,1085,1355239085),(986412,1085,1355239086),(986413,1085,1355239088),(986414,1046,1355839401),(986414,1085,1355239090),(986415,1085,1355239094),(986416,1085,1355239095),(986417,1085,1355239098),(986418,1085,1355239102),(986419,1085,1355239103),(986420,1085,1355239115),(986421,1085,1355239115),(986422,1085,1355239126),(986423,1085,1355239130),(986424,1085,1355239131),(986425,1085,1355239131),(986426,1085,1355239132),(986427,1085,1355239137),(986428,1085,1355239189),(986429,1085,1355239158),(986430,1085,1355239158),(986431,1085,1355239162),(986432,1085,1355239164),(986433,1085,1355239176),(986434,1085,1355239178),(986435,1085,1355239179),(986436,1085,1355239184),(986437,1085,1355329357),(986438,1085,1355239193),(986439,1085,1355239195),(986440,1085,1355239747),(986441,1085,1355239212),(986442,1085,1355239215),(986443,1085,1355239219),(986444,1085,1355239220),(986445,1085,1355239229),(986446,1085,1355239233),(986447,1085,1355239233),(986448,1085,1355239242),(986449,1085,1355239264),(986450,1085,1355239249),(986451,1085,1355239251),(986452,1085,1355239285),(986453,1085,1355239287),(986454,1085,1355239297),(986455,1085,1355239298),(986456,1085,1355239301),(986457,1085,1355239310),(986458,1085,1355239332),(986459,1085,1355239348),(986460,1085,1355239363),(986461,1085,1355239384),(986462,1085,1355239548),(986463,1085,1355239421),(986464,1085,1355239431),(986465,1085,1355239433),(986466,1085,1355239441),(986467,1085,1355239444),(986468,1085,1355239444),(986469,1085,1355239465),(986470,1085,1355239468),(986471,1085,1355239531),(986472,1085,1355239477),(986473,1085,1355239496),(986474,1085,1355239507),(986475,1085,1355239510),(986476,1085,1355239522),(986477,1085,1355239529),(986478,1085,1355239529),(986479,1085,1355239534),(986480,1085,1355239540),(986481,1085,1355239553),(986482,1085,1355239566),(986483,1085,1355239590),(986484,1085,1355239603),(986485,1085,1355239607),(986486,1085,1355239633),(986487,1085,1355239626),(986488,1085,1355239628),(986489,1085,1355239637),(986490,1085,1355239638),(986491,1085,1355239640),(986492,1085,1355239642),(986493,1085,1355239751),(986494,1085,1355239671),(986495,1085,1355239677),(986496,1085,1355239700),(986497,1085,1355239703),(986498,1085,1355239715),(986499,1085,1355239723),(986500,1085,1355239727),(986501,1085,1355239769),(986502,1085,1355239732),(986503,1085,1355239745),(986504,1085,1355239750),(986505,1085,1355239752),(986506,1085,1355239795),(986507,1085,1355239768),(986508,1085,1355239785),(986509,1085,1355239790),(986510,1085,1355239794),(986511,1085,1355239798),(986512,1085,1355239802),(986513,1085,1355239802),(986514,1085,1355239805),(986515,1085,1355239822),(986516,1085,1355239831),(986517,1085,1355239852),(986518,1085,1355239854),(986519,1085,1355239861),(986520,1085,1355239861),(986521,1085,1355239865),(986522,1085,1355239866),(986523,1085,1355239905),(986524,1085,1355239878),(986525,1085,1355239878),(986526,1085,1355239879),(986527,1085,1355246709),(986528,1085,1355239885),(986529,1045,1355239908),(986529,1085,1355239887),(986530,1085,1355239888),(986531,1085,1355239888),(986532,1045,1355239903),(986532,1085,1355239891),(986533,1085,1355239892),(986534,1085,1355239902),(986535,1085,1355239908),(986536,1085,1355239922),(986537,1085,1355239922),(986538,1085,1355239923),(986539,1085,1355239943),(986540,1085,1355239928),(986541,1085,1355239929),(986542,1085,1355239931),(986543,1085,1355239932),(986544,1085,1355239947),(986545,1085,1355239957),(986546,1045,1355240007),(986546,1085,1355239982),(986547,1085,1355239989),(986548,1085,1355239996),(986549,1085,1355240001),(986550,1085,1355240017),(986551,1085,1355240033),(986552,1085,1355240034),(986553,1085,1355240040),(986554,1085,1355240042),(986555,1085,1355240043),(986556,1085,1355240054),(986557,1085,1355242399),(986558,1085,1355240061),(986559,1085,1355240062),(986560,1085,1355240062),(986561,1085,1355240068),(986562,1085,1355240071),(986563,1085,1355240072),(986564,1085,1355240075),(986565,1085,1355240076),(986566,1085,1355240082),(986567,1085,1355240348),(986568,1085,1355240104),(986569,1085,1355240115),(986570,1085,1355240116),(986571,1085,1355240173),(986572,1085,1355240119),(986573,1085,1355240120),(986574,1085,1355240126),(986575,1046,1355814050),(986575,1085,1355240136),(986576,1085,1355240136),(986577,1085,1355240137),(986578,1085,1355240141),(986579,1085,1355240142),(986580,1085,1355240151),(986581,1085,1355240154),(986582,1085,1355240156),(986583,1085,1355240161),(986584,1085,1355240165),(986585,1085,1355240166),(986586,1085,1355240242),(986587,1085,1355240179),(986588,1085,1355240189),(986589,1085,1355240205),(986590,1085,1355240220),(986591,1085,1355240227),(986592,1085,1355240233),(986593,1085,1355240238),(986594,1045,1355346989),(986594,1085,1355240241),(986595,1085,1355240243),(986596,1085,1355240248),(986597,1085,1355240257),(986598,1085,1355240267),(986599,1085,1355240268),(986600,1085,1355240268),(986601,1085,1355240271),(986602,1085,1355240275),(986603,1085,1355240341),(986604,1085,1355240296),(986605,1085,1355240298),(986606,1085,1355240316),(986607,1085,1355240320),(986608,1085,1355240326),(986609,1085,1355240327),(986610,1085,1355240331),(986611,1085,1355240342),(986612,1085,1355240351),(986613,1085,1355240352),(986614,1085,1355240375),(986615,1085,1355240401),(986616,1085,1355240403),(986617,1085,1355240402),(986618,1085,1355240411),(986619,1085,1355240423),(986620,1085,1355240424),(986621,1085,1355240430),(986622,1085,1355240441),(986623,1085,1355240443),(986624,1085,1355240745),(986625,1085,1355240454),(986626,1085,1355240460),(986627,1085,1355240461),(986628,1085,1355240462),(986629,1085,1355240462),(986630,1085,1355240463),(986631,1085,1355240464),(986632,1085,1355240469),(986633,1085,1355240481),(986634,1085,1355240495),(986635,1085,1355240504),(986636,1085,1355240514),(986637,1085,1355240523),(986638,1085,1355240525),(986639,1085,1355240527),(986640,1085,1355240529),(986641,1085,1355240529),(986642,1085,1355240573),(986643,1085,1355240762),(986644,1085,1355240597),(986645,1085,1355240600),(986646,1085,1355240603),(986647,1085,1355240605),(986648,1085,1355240619),(986649,1085,1355240646),(986650,1085,1355240652),(986651,1085,1355240658),(986652,1085,1355240661),(986653,1085,1355240661),(986654,1085,1355240661),(986655,1085,1355240665),(986656,1085,1355240675),(986657,1085,1355240678),(986658,1085,1355240682),(986659,1085,1355240682),(986660,1085,1355240696),(986661,1085,1355240701),(986662,1085,1355240704),(986663,1085,1355240806),(986664,1085,1355240733),(986665,1085,1355240724),(986666,1085,1355240731),(986667,1085,1355240743),(986669,1085,1355240753),(986670,1085,1355240754),(986671,1085,1355240777),(986672,1085,1355240782),(986673,1085,1355240792),(986674,1085,1355240799),(986675,1085,1355240799),(986676,1085,1355240799),(986677,1085,1355240820),(986678,1085,1355240824),(986679,1085,1355240833),(986680,1085,1355240833),(986681,1085,1355240849),(986682,1085,1355240853),(986683,1085,1355240867),(986684,1085,1355240873),(986685,1085,1355240874),(986686,1085,1355240878),(986687,1085,1355240879),(986688,1085,1355240880),(986689,1085,1355240892),(986690,1085,1355240897),(986691,1085,1355240899),(986692,1085,1355240904),(986693,1085,1355240933),(986694,1085,1355240936),(986695,1085,1355240940),(986696,1085,1355240947),(986697,1085,1355240955),(986698,1085,1355429169),(986699,1085,1355240959),(986700,1085,1355240959),(986701,1085,1355240961),(986702,1085,1355240966),(986703,1085,1355240968),(986704,1085,1355240979),(986705,1085,1355240980),(986706,1085,1355241021),(986707,1085,1355241045),(986708,1085,1355241051),(986709,1085,1355241055),(986710,1085,1355241064),(986711,1085,1355241065),(986712,1085,1355241070),(986713,1085,1355241072),(986714,1085,1355241076),(986715,1085,1355241076),(986716,1085,1355241093),(986717,1085,1355241096),(986718,1085,1355241096),(986719,1085,1355241098),(986720,1085,1355241100),(986721,1085,1355241101),(986722,1085,1355241114),(986723,1085,1355241127),(986724,1085,1355241128),(986725,1085,1355241133),(986726,1085,1355241134),(986727,1085,1355241139),(986728,1085,1355241229),(986729,1085,1355241150),(986730,1085,1355241150),(986731,1085,1355241154),(986732,1085,1355280547),(986733,1085,1355241156),(986734,1085,1355241158),(986735,1085,1355241179),(986736,1085,1355241187),(986737,1085,1355241192),(986738,1085,1355241202),(986739,1085,1355241228),(986740,1085,1355241244),(986741,1085,1355241250),(986742,1085,1355241267),(986743,1085,1355241293),(986744,1085,1355241315),(986745,1085,1355241327),(986746,1085,1355241333),(986747,1085,1355241334),(986748,1085,1355241338),(986749,1085,1355241339),(986750,1085,1355241355),(986751,1085,1355241357),(986752,1085,1355241364),(986753,1085,1355241365),(986754,1085,1355241368),(986755,1045,1355848958),(986755,1085,1355241376),(986756,1085,1355241381),(986757,1085,1355249956),(986758,1085,1355241387),(986759,1085,1355241391),(986760,1085,1355241394),(986761,1085,1355241395),(986762,1085,1355241401),(986763,1085,1355241414),(986764,1085,1355241428),(986765,1085,1355241432),(986766,1085,1355241432),(986767,1085,1355241432),(986768,1085,1355241446),(986769,1085,1355241457),(986770,1085,1355241477),(986771,1085,1355241485),(986772,1085,1355241490),(986773,1085,1355241502),(986774,1085,1355241516),(986775,1085,1355241519),(986776,1085,1355241523),(986777,1085,1355241532),(986778,1085,1355241537),(986779,1085,1355275073),(986780,1085,1355241568),(986781,1085,1355241589),(986782,1085,1355241597),(986783,1085,1355241597),(986784,1085,1355241603),(986785,1085,1355241626),(986786,1085,1355241628),(986787,1085,1355241632),(986788,1085,1355241632),(986789,1085,1355241646),(986790,1085,1355241647),(986791,1085,1355241648),(986792,1085,1355241652),(986793,1085,1355241655),(986794,1085,1355241662),(986795,1085,1355241669),(986796,1085,1355241679),(986797,1085,1355241689),(986798,1085,1355241716),(986799,1085,1355241725),(986800,1085,1355241728),(986801,1085,1355241729),(986802,1085,1355241743),(986803,1085,1355241756),(986804,1085,1355241811),(986805,1085,1355241775),(986806,1085,1355241790),(986807,1085,1355241792),(986808,1085,1355241839),(986809,1085,1355242396),(986810,1085,1355241916),(986811,1085,1355241854),(986812,1085,1355241856),(986813,1085,1355241859),(986814,1085,1355241861),(986815,1085,1355241890),(986816,1085,1355241903),(986817,1085,1355241912),(986818,1085,1355241912),(986819,1085,1355241926),(986820,1085,1355241929),(986821,1085,1355241936),(986822,1085,1355241942),(986823,1085,1355241944),(986824,1085,1355241983),(986825,1085,1355241983),(986826,1085,1355242003),(986827,1085,1355242011),(986828,1085,1355242141),(986829,1085,1355242075),(986830,1085,1355242050),(986831,1085,1355242065),(986832,1085,1355242075),(986833,1085,1355242078),(986834,1085,1355242080),(986835,1085,1355242083),(986836,1085,1355242092),(986837,1085,1355242122),(986838,1085,1355242096),(986839,1085,1355242101),(986840,1085,1355242102),(986841,1085,1355242112),(986842,1085,1355242113),(986843,1085,1355242139),(986844,1085,1355242144),(986845,1085,1355242145),(986846,1085,1355242147),(986847,1085,1355242147),(986848,1085,1355242158),(986849,1085,1355242171),(986850,1085,1355242175),(986851,1085,1355242175),(986852,1085,1355242188),(986853,1085,1355242189),(986854,1085,1355242197),(986855,1085,1355242214),(986856,1085,1355242215),(986857,1085,1355242223),(986858,1085,1355242229),(986859,1085,1355242250),(986860,1085,1355242259),(986861,1085,1355242261),(986862,1085,1355242271),(986863,1085,1355242277),(986864,1085,1355242278),(986865,1085,1355242282),(986866,1085,1355242283),(986867,1085,1355242295),(986868,1085,1355242299),(986869,1085,1355242303),(986870,1045,1356046248),(986870,1085,1355242313),(986871,1085,1355242343),(986872,1085,1355242373),(986873,1085,1355242336),(986874,1085,1355242337),(986875,1085,1355242342),(986876,1085,1355242347),(986877,1085,1355242353),(986878,1085,1355242356),(986879,1085,1355242364),(986880,1085,1355242368),(986881,1085,1355242376),(986882,1085,1355242382),(986883,1085,1355242390),(986884,1085,1355242399),(986885,1085,1355242401),(986886,1085,1355242418),(986887,1085,1355242426),(986888,1085,1355242474),(986889,1085,1355242475),(986890,1085,1355242529),(986891,1085,1355242532),(986892,1085,1355242556),(986893,1085,1355242570),(986894,1045,1355242581),(986894,1085,1355242578),(986895,1085,1355242580),(986896,1085,1355242602),(986897,1085,1355242604),(986898,1085,1355242621),(986899,1085,1355242626),(986900,1085,1355242634),(986901,1085,1355242636),(986902,1085,1355242642),(986903,1085,1355242648),(986904,1085,1355242648),(986905,1085,1355242648),(986906,1085,1355242649),(986907,1085,1355242652),(986908,1085,1355242659),(986909,1085,1355242669),(986910,1085,1355242673),(986911,1085,1355242679),(986912,1085,1355242682),(986913,1085,1355242689),(986914,1085,1355242689),(986915,1085,1355242708),(986916,1085,1355242712),(986917,1085,1355242719),(986918,1085,1355242720),(986919,1085,1355242723),(986920,1085,1355242725),(986921,1085,1355242747),(986922,1045,1355242765),(986922,1085,1355242749),(986923,1085,1355242749),(986924,1085,1355242759),(986925,1085,1355242762),(986926,1085,1355242765),(986927,1085,1355242766),(986928,1085,1355242782),(986929,1085,1355242794),(986930,1085,1355242799),(986931,1085,1355242813),(986932,1085,1355242816),(986933,1085,1355242820),(986934,1085,1355242829),(986935,1085,1355242849),(986936,1085,1355242831),(986937,1085,1355242832),(986938,1085,1355242836),(986939,1085,1355242849),(986940,1085,1355242864),(986941,1085,1355242878),(986942,1085,1355242890),(986943,1085,1355242891),(986944,1085,1355242899),(986945,1085,1355243252),(986946,1085,1355243061),(986947,1085,1355242946),(986948,1085,1355242947),(986949,1085,1355242950),(986950,1085,1355242972),(986950,1236,1355243029),(986951,1085,1355242983),(986952,1085,1355242984),(986953,1085,1355243056),(986954,1085,1355243075),(986955,1085,1355243082),(986956,1085,1355243084),(986957,1085,1355243089),(986958,1085,1355243092),(986959,1085,1355243102),(986960,1085,1355243113),(986961,1085,1355243116),(986962,1085,1355243130),(986963,1085,1355243132),(986964,1085,1355243148),(986965,1085,1355243149),(986966,1085,1355243172),(986967,1085,1355243176),(986968,1085,1355243182),(986969,1085,1355243187),(986970,1085,1355243202),(986971,1085,1355243233),(986972,1085,1355243233),(986973,1085,1355243243),(986974,1085,1355243254),(986975,1085,1355243258),(986976,1085,1355243290),(986977,1085,1355243299),(986978,1085,1355243299),(986979,1085,1355243308),(986980,1085,1355243326),(986981,1085,1355243328),(986982,1085,1355243345),(986983,1085,1355243347),(986984,1085,1355243359),(986985,1085,1355243386),(986986,1085,1355243401),(986987,1085,1355243420),(986988,1085,1355243444),(986989,1085,1355243452),(986990,1085,1355243491),(986991,1085,1355243501),(986992,1085,1355243510),(986993,1085,1355243533),(986994,1085,1355243539),(986995,1085,1355243548),(986996,1085,1355243548),(986997,1085,1355243551),(986998,1085,1355243557),(986999,1085,1355243596),(987000,1085,1355243560),(987001,1085,1355243566),(987002,1085,1355243568),(987003,1085,1355243585),(987004,1085,1355243588),(987005,1085,1355243591),(987006,1085,1355243666),(987007,1085,1355243652),(987008,1085,1355243659),(987009,1085,1355243668),(987010,1085,1355243668),(987011,1085,1355243677),(987012,1085,1355243678),(987013,1085,1355243686),(987014,1085,1355243694),(987015,1085,1355243697),(987016,1085,1355243710),(987017,1085,1355243723),(987018,1085,1355243735),(987019,1085,1355243747),(987020,1085,1355243756),(987021,1085,1355243757),(987022,1085,1355243758),(987023,1085,1355243764),(987024,1085,1355243768),(987025,1085,1355243828),(987026,1085,1355243795),(987027,1085,1355244023),(987028,1085,1355243835),(987029,1085,1355243840),(987030,1085,1355243841),(987031,1085,1355243849),(987032,1085,1355243853),(987033,1085,1355243854),(987034,1085,1355243857),(987035,1085,1355249068),(987036,1085,1355243859),(987037,1085,1355243860),(987038,1085,1355243870),(987039,1085,1355243875),(987040,1085,1355243877),(987041,1085,1355243878),(987042,1085,1355243885),(987043,1085,1355243907),(987044,1085,1355243907),(987045,1085,1355243914),(987046,1085,1355243915),(987047,1085,1355243915),(987048,1085,1355244580),(987049,1085,1355243945),(987050,1085,1355243954),(987051,1085,1355243960),(987051,1236,1355244543),(987052,1085,1355386227),(987053,1085,1355243993),(987054,1085,1355243996),(987055,1085,1355244049),(987056,1085,1355244059),(987057,1085,1355244062),(987058,1085,1355244066),(987059,1085,1355244067),(987060,1085,1355244074),(987061,1085,1355244079),(987062,1085,1355244112),(987063,1085,1355244119),(987064,1085,1355244127),(987065,1085,1355244140),(987066,1085,1355244146),(987067,1085,1355244149),(987068,1085,1355244149),(987069,1085,1355244163),(987070,1085,1355244164),(987071,1085,1355244166),(987072,1085,1355244214),(987073,1085,1355244228),(987074,1085,1355244244),(987075,1085,1355244248),(987076,1085,1355244250),(987077,1085,1355244253),(987078,1085,1355244259),(987079,1085,1355244270),(987080,1085,1355244276),(987081,1085,1355244311),(987082,1085,1355244314),(987083,1085,1355244316),(987084,1085,1355244322),(987085,1085,1355244324),(987086,1085,1355244333),(987087,1085,1355244350),(987088,1085,1355244352),(987089,1085,1355244354),(987090,1085,1355244694),(987091,1085,1355244378),(987092,1085,1355244406),(987093,1085,1355244412),(987094,1085,1355244425),(987095,1085,1355244425),(987096,1085,1355244684),(987096,1236,1355244701),(987097,1085,1355244428),(987098,1085,1355244429),(987099,1085,1355244456),(987100,1085,1355244458),(987101,1085,1355244466),(987102,1085,1355244469),(987103,1085,1355244473),(987104,1085,1355244474),(987105,1085,1355244487),(987106,1085,1355244491),(987107,1085,1355244505),(987108,1085,1355244506),(987109,1085,1355244510),(987110,1085,1355244522),(987111,1085,1355244535),(987112,1085,1355244537),(987113,1085,1355244551),(987114,1085,1355244552),(987115,1085,1355244553),(987116,1085,1355244566),(987117,1085,1355244588),(987118,1085,1355244590),(987119,1085,1355244624),(987120,1085,1355244634),(987121,1085,1355244640),(987122,1085,1355244641),(987123,1085,1355244642),(987124,1085,1355244675),(987125,1085,1355244692),(987126,1085,1355244714),(987127,1085,1355244714),(987128,1085,1355244717),(987129,1046,1355244817),(987130,1085,1355244738),(987131,1085,1355244745),(987132,1085,1355244771),(987133,1085,1355244808),(987134,1085,1355244820),(987135,1085,1355244820),(987136,1085,1355244832),(987137,1085,1355244862),(987138,1085,1355244871),(987139,1045,1355244889),(987139,1085,1355244886),(987140,1085,1355244890),(987141,1085,1355244895),(987142,1085,1355244908),(987143,1085,1355244915),(987144,1085,1355244932),(987145,1085,1355244952),(987146,1085,1355244960),(987147,1085,1355244981),(987148,1085,1355244985),(987149,1085,1355244994),(987150,1085,1355244996),(987151,1085,1355245021),(987152,1085,1355245007),(987153,1085,1355245008),(987154,1085,1355416988),(987155,1085,1355245022),(987156,1085,1355245030),(987157,1085,1355245045),(987158,1085,1355245071),(987159,1085,1355245090),(987160,1085,1355245096),(987161,1085,1355245239),(987162,1085,1355245151),(987163,1085,1355245161),(987164,1085,1355262928),(987165,1085,1355245163),(987166,1085,1355245184),(987167,1085,1355245172),(987168,1085,1355245181),(987169,1085,1355245204),(987170,1085,1355245189),(987171,1085,1355245198),(987172,1085,1355245206),(987173,1085,1355245207),(987174,1085,1355245211),(987175,1085,1355245211),(987176,1085,1355245215),(987177,1085,1355245221),(987178,1085,1355245225),(987179,1046,1358021435),(987179,1085,1355245224),(987180,1085,1355245235),(987181,1085,1355245240),(987182,1085,1355245408),(987183,1045,1355245444),(987183,1085,1355245248),(987184,1085,1355245253),(987185,1085,1355245291),(987186,1085,1355245337),(987187,1085,1355245342),(987188,1085,1355245347),(987189,1085,1355245387),(987190,1085,1355245387),(987191,1085,1355245393),(987192,1085,1355245395),(987193,1085,1355245401),(987194,1085,1355245417),(987195,1085,1355245436),(987196,1085,1355245438),(987197,1085,1355245443),(987198,1085,1355299002),(987198,1236,1355808547),(987199,1085,1355245506),(987200,1085,1355245507),(987201,1085,1355245509),(987202,1085,1355245580),(987203,1085,1355245515),(987204,1085,1355245523),(987205,1085,1355245535),(987206,1085,1355245549),(987207,1085,1355245565),(987208,1085,1355245567),(987209,1085,1355245584),(987210,1085,1355245592),(987211,1085,1355245593),(987212,1045,1355245616),(987212,1085,1355245597),(987213,1085,1355245598),(987214,1085,1355245612),(987215,1085,1355245620),(987216,1085,1355245655),(987217,1085,1355245787),(987218,1085,1355245680),(987219,1085,1355245689),(987220,1085,1355245693),(987221,1085,1355245694),(987222,1085,1355245695),(987223,1085,1355245795),(987224,1085,1355245722),(987225,1085,1355245735),(987226,1085,1355245738),(987227,1085,1355245752),(987228,1085,1355245766),(987229,1045,1355245804),(987229,1085,1355245801),(987230,1085,1355245852),(987231,1085,1355245875),(987232,1085,1355245882),(987233,1085,1355246112),(987234,1085,1355245891),(987235,1085,1355245917),(987236,1085,1355245929),(987237,1085,1355245949),(987238,1085,1355245952),(987239,1085,1355245978),(987240,1085,1355245983),(987241,1085,1355245986),(987242,1085,1355246004),(987243,1085,1355246014),(987244,1085,1355246014),(987245,1085,1355246038),(987246,1085,1355246045),(987247,1085,1355246068),(987248,1085,1355246073),(987249,1045,1355349266),(987249,1085,1355246087),(987250,1085,1355246089),(987251,1085,1355246124),(987252,1085,1355246153),(987253,1085,1355246156),(987254,1085,1355246178),(987255,1085,1355246188),(987256,1085,1355246250),(987257,1085,1355246201),(987258,1085,1355246208),(987259,1085,1355246217),(987260,1085,1355246240),(987261,1085,1355246244),(987262,1085,1355246246),(987263,1085,1355246262),(987264,1085,1355246263),(987265,1085,1355246268),(987266,1085,1355246295),(987267,1085,1355246312),(987268,1085,1355246322),(987269,1085,1355246328),(987270,1042,1357336845),(987270,1046,1357336847),(987270,1085,1355246336),(987271,1085,1355246346),(987272,1085,1355246349),(987273,1085,1355246352),(987274,1085,1355246353),(987275,1085,1355246361),(987276,1085,1355246366),(987277,1085,1355246403),(987278,1085,1355246403),(987279,1085,1355246429),(987280,1085,1355246432),(987281,1085,1355246438),(987282,1085,1355246457),(987283,1085,1355246482),(987284,1085,1355246488),(987285,1085,1355246537),(987286,1085,1355246510),(987287,1085,1355246524),(987288,1085,1355246527),(987289,1085,1355246564),(987290,1085,1355246567),(987291,1085,1355246574),(987292,1085,1355246580),(987293,1085,1355246582),(987294,1085,1355246585),(987295,1085,1355246602),(987296,1085,1355246615),(987297,1085,1355246617),(987298,1085,1355246625),(987299,1085,1355246640),(987300,1085,1355246644),(987301,1085,1355247038),(987302,1085,1355246725),(987303,1085,1355246727),(987304,1085,1355246750),(987305,1085,1355246758),(987306,1085,1355246776),(987307,1045,1355246795),(987308,1085,1355246796),(987309,1085,1355246812),(987310,1085,1355246824),(987311,1085,1355246826),(987312,1085,1355246842),(987313,1085,1355246849),(987314,1085,1355246867),(987315,1085,1355246875),(987316,1085,1355246880),(987317,1085,1355246906),(987318,1085,1355246908),(987319,1085,1355246936),(987320,1085,1355246940),(987321,1085,1355246944),(987322,1085,1355246977),(987323,1085,1355246992),(987324,1085,1355247002),(987325,1085,1355247025),(987326,1085,1355247047),(987327,1085,1355247063),(987328,1085,1355247104),(987329,1085,1355247107),(987330,1085,1355247117),(987331,1085,1355247123),(987332,1085,1355247126),(987333,1085,1355247167),(987334,1085,1355247185),(987335,1085,1355247187),(987336,1085,1355247188),(987337,1085,1355247211),(987338,1085,1355247216),(987339,1085,1355247216),(987340,1085,1355247219),(987341,1085,1355247220),(987342,1085,1355247227),(987343,1085,1355247246),(987344,1085,1355247357),(987345,1085,1355247281),(987346,1085,1355247283),(987347,1085,1355247319),(987348,1085,1355247329),(987349,1085,1355247329),(987350,1085,1355247330),(987351,1046,1355884420),(987351,1085,1355247336),(987352,1085,1355247342),(987353,1085,1355247350),(987354,1085,1355247361),(987355,1085,1355247370),(987356,1085,1355247381),(987357,1085,1355247614),(987358,1085,1355247393),(987359,1085,1355247403),(987360,1085,1355247412),(987361,1085,1355247427),(987362,1085,1355247562),(987363,1085,1355247527),(987364,1085,1355247481),(987365,1085,1355247487),(987366,1085,1355247489),(987367,1085,1355247532),(987368,1085,1355247545),(987369,1085,1355247553),(987370,1085,1355247586),(987371,1085,1355247588),(987372,1085,1355247635),(987373,1085,1355247647),(987374,1085,1355247650),(987375,1085,1355247658),(987376,1045,1355848603),(987376,1085,1355247661),(987377,1085,1355247670),(987378,1085,1355247681),(987379,1085,1355247681),(987380,1085,1355247700),(987381,1085,1355247715),(987382,1085,1355247718),(987383,1085,1355247721),(987384,1085,1355247740),(987385,1085,1355247775),(987386,1085,1355247789),(987387,1085,1355247802),(987388,1085,1355247804),(987389,1085,1355247806),(987390,1085,1355247808),(987391,1085,1355247852),(987392,1085,1355247869),(987393,1085,1355247885),(987394,1085,1355247889),(987395,1085,1355247905),(987396,1085,1355247925),(987397,1085,1355247930),(987398,1085,1355247938),(987399,1085,1355247950),(987400,1085,1355247951),(987401,1085,1355247976),(987402,1085,1355247995),(987403,1085,1355247996),(987404,1085,1355248015),(987405,1085,1355248024),(987406,1085,1355248062),(987407,1085,1355248068),(987408,1085,1355248070),(987409,1085,1355248091),(987410,1085,1355248092),(987411,1085,1355248741),(987412,1085,1355248170),(987413,1085,1355248171),(987414,1085,1355248240),(987415,1045,1357328056),(987415,1085,1355248221),(987415,1236,1357328793),(987416,1085,1355248230),(987417,1085,1355248233),(987418,1085,1355248260),(987419,1085,1355248262),(987420,1085,1355248288),(987421,1085,1355248304),(987422,1085,1355248322),(987423,1085,1355248327),(987424,1085,1355248341),(987425,1085,1355248347),(987426,1085,1355248418),(987427,1085,1355248361),(987428,1085,1355248380),(987429,1085,1355248382),(987430,1085,1355248386),(987431,1085,1355248685),(987432,1085,1355248421),(987433,1085,1355248422),(987434,1085,1355250297),(987435,1085,1355248441),(987436,1085,1355248447),(987437,1085,1355248550),(987438,1085,1355248480),(987439,1085,1355248520),(987440,1085,1355248520),(987441,1085,1355248520),(987442,1085,1355248534),(987443,1085,1355248535),(987444,1085,1355248536),(987445,1085,1355248540),(987446,1085,1355248552),(987447,1085,1355248583),(987448,1085,1355248595),(987449,1085,1355248599),(987450,1085,1355248608),(987451,1085,1355248662),(987452,1085,1355248674),(987453,1085,1355248685),(987454,1085,1355248692),(987455,1085,1355248710),(987456,1085,1355248720),(987457,1085,1355248721),(987458,1085,1355248723),(987459,1085,1355248727),(987460,1085,1355248757),(987461,1085,1355248786),(987462,1085,1355248797),(987463,1045,1355248821),(987463,1085,1355248807),(987464,1085,1355248814),(987465,1085,1355248833),(987466,1085,1355248869),(987467,1085,1355248891),(987467,1236,1355248956),(987468,1085,1355248913),(987469,1085,1355248940),(987470,1085,1355248960),(987470,1236,1355534772),(987471,1085,1355248965),(987472,1085,1355248972),(987473,1085,1355248989),(987474,1085,1355249009),(987475,1085,1355249012),(987476,1085,1355249032),(987477,1085,1355249070),(987478,1085,1355249089),(987479,1085,1355249092),(987480,1085,1355249125),(987481,1085,1355249126),(987482,1085,1355249127),(987483,1085,1355249127),(987484,1085,1355249141),(987485,1085,1355249160),(987486,1085,1355249183),(987487,1085,1355249215),(987488,1085,1355249308),(987489,1085,1355249235),(987490,1085,1355249241),(987491,1085,1355249256),(987492,1085,1355249268),(987493,1085,1355249290),(987494,1085,1355249294),(987495,1085,1355250153),(987496,1085,1355249299),(987497,1085,1355249306),(987498,1085,1355249313),(987499,1085,1355249365),(987500,1085,1355249387),(987500,1236,1355249529),(987501,1085,1355249390),(987502,1085,1355249392),(987503,1085,1355249405),(987504,1085,1355249409),(987505,1085,1355249428),(987506,1085,1355249438),(987507,1085,1355249449),(987508,1085,1355249458),(987509,1085,1355249466),(987510,1085,1355249540),(987511,1085,1355249610),(987512,1085,1355249625),(987513,1085,1355249643),(987514,1085,1355249691),(987515,1085,1355249691),(987516,1085,1355249695),(987517,1045,1355250721),(987517,1085,1355249731),(987518,1085,1355249713),(987519,1085,1355249740),(987520,1085,1355249740),(987521,1085,1355249753),(987522,1085,1355249791),(987523,1085,1355249794),(987524,1085,1355249821),(987525,1085,1355249822),(987526,1085,1355249823),(987527,1085,1355249842),(987528,1085,1355249878),(987529,1085,1355249893),(987530,1085,1355249900),(987531,1085,1355249902),(987532,1085,1355249972),(987533,1085,1355249972),(987534,1085,1355250039),(987535,1085,1355250052),(987536,1085,1355250072),(987537,1085,1355250094),(987538,1085,1355250144),(987539,1085,1355250260),(987540,1085,1355250191),(987541,1085,1355250169),(987542,1085,1355250186),(987543,1085,1355250189),(987544,1085,1355250193),(987545,1085,1355250199),(987546,1085,1355250202),(987547,1085,1355250206),(987548,1085,1355250213),(987549,1085,1355250215),(987550,1085,1355250216),(987551,1085,1355250216),(987552,1085,1355250224),(987553,1085,1355250248),(987554,1085,1355250288),(987555,1085,1355250298),(987556,1085,1355250309),(987557,1085,1355250331),(987558,1085,1355250338),(987559,1085,1355250463),(987560,1085,1355250352),(987561,1085,1355250372),(987562,1085,1355250389),(987563,1085,1355250394),(987564,1085,1355250404),(987565,1085,1355250407),(987566,1085,1355250407),(987567,1085,1355250413),(987568,1085,1355250415),(987569,1085,1355250425),(987570,1085,1355250440),(987571,1085,1355250461),(987572,1085,1355250487),(987573,1085,1355250496),(987574,1085,1355250522),(987575,1085,1355250527),(987576,1085,1355250529),(987577,1085,1355250560),(987578,1085,1355250565),(987579,1085,1355250568),(987580,1085,1355250585),(987581,1085,1355250617),(987582,1085,1355250641),(987583,1045,1355266782),(987583,1085,1355250643),(987584,1085,1355250645),(987585,1085,1355250655),(987586,1085,1355250655),(987587,1085,1355250660),(987588,1085,1355250676),(987589,1085,1355250676),(987590,1085,1355250679),(987591,1085,1355250685),(987592,1085,1355250733),(987593,1085,1355250736),(987594,1085,1355250748),(987595,1085,1355250785),(987596,1085,1355250790),(987597,1085,1355250799),(987598,1085,1355250808),(987599,1085,1355250813),(987600,1085,1355250819),(987601,1085,1355250822),(987602,1085,1355250829),(987603,1085,1355250830),(987604,1085,1355250876),(987605,1085,1355250897),(987606,1085,1355250916),(987607,1085,1355250926),(987608,1085,1355250963),(987609,1085,1355250975),(987610,1085,1355250983),(987611,1085,1355251010),(987612,1085,1355251012),(987613,1085,1355251074),(987614,1085,1355251084),(987615,1085,1355251125),(987616,1085,1355251125),(987617,1085,1355251140),(987618,1085,1355251144),(987619,1085,1355251167),(987620,1085,1355251170),(987621,1085,1355251192),(987622,1085,1355251197),(987623,1085,1355251292),(987624,1085,1355251216),(987625,1085,1355251201),(987626,1085,1355251221),(987627,1085,1355251222),(987628,1085,1355251223),(987629,1085,1355251248),(987630,1085,1355251257),(987631,1085,1355251386),(987632,1085,1355251324),(987633,1046,1355251432),(987633,1085,1355251336),(987634,1085,1355251358),(987635,1085,1355251364),(987636,1085,1355251418),(987637,1085,1355251431),(987638,1085,1355251434),(987639,1085,1355251446),(987640,1085,1355251494),(987641,1085,1355251511),(987642,1085,1355251511),(987643,1085,1355251515),(987644,1085,1355251526),(987645,1085,1355251536),(987646,1085,1355251539),(987647,1085,1355251627),(987648,1085,1355251629),(987649,1085,1355251632),(987650,1085,1355251667),(987651,1085,1355251670),(987652,1085,1355251671),(987653,1085,1355251696),(987654,1085,1355251736),(987655,1085,1355251757),(987656,1085,1355251783),(987657,1085,1355251790),(987658,1085,1355251819),(987659,1085,1355251845),(987660,1045,1355251907),(987660,1085,1355251858),(987661,1085,1355251864),(987662,1085,1355251868),(987663,1085,1355251916),(987664,1085,1355251927),(987665,1085,1355251951),(987666,1085,1355251981),(987667,1085,1355251984),(987668,1085,1355252001),(987669,1085,1355252004),(987670,1085,1355252005),(987671,1085,1355252005),(987672,1085,1355252017),(987673,1085,1355252026),(987674,1085,1355252039),(987675,1085,1355252042),(987676,1085,1355252050),(987677,1085,1355252077),(987678,1085,1355252149),(987679,1085,1355252171),(987680,1085,1355252179),(987681,1085,1355252190),(987682,1085,1355252191),(987683,1085,1355252220),(987684,1085,1355252233),(987685,1085,1355252258),(987686,1085,1355252298),(987687,1085,1355252352),(987688,1085,1355252382),(987689,1085,1355252419),(987690,1085,1355252443),(987691,1085,1355252446),(987692,1085,1355252477),(987693,1085,1355252477),(987694,1085,1355252490),(987695,1085,1355252491),(987696,1085,1355252495),(987697,1085,1355252507),(987698,1085,1355252511),(987699,1085,1355252515),(987700,1085,1355252554),(987701,1085,1355252539),(987702,1085,1355252545),(987703,1085,1355252545),(987704,1085,1355252575),(987705,1085,1355252591),(987706,1085,1355252592),(987707,1085,1355252640),(987708,1085,1355253380),(987709,1085,1355252662),(987710,1085,1355252708),(987711,1085,1355252715),(987712,1085,1355252809),(987713,1085,1355252766),(987714,1085,1355252778),(987715,1085,1355252850),(987716,1085,1355252908),(987717,1085,1355252914),(987718,1085,1355252924),(987719,1085,1355252961),(987720,1085,1355253065),(987721,1085,1355253012),(987722,1085,1355253013),(987723,1085,1355253013),(987724,1085,1355253021),(987725,1085,1355253049),(987726,1085,1355253050),(987727,1085,1355253054),(987728,1085,1355253065),(987729,1085,1355253096),(987730,1085,1355253120),(987731,1085,1355253131),(987732,1085,1355253162),(987733,1085,1355253197),(987734,1085,1355253214),(987735,1085,1355253236),(987736,1085,1355253236),(987737,1085,1355253237),(987738,1085,1355253258),(987739,1085,1355253260),(987740,1085,1355253308),(987741,1085,1355253325),(987742,1085,1355253326),(987743,1085,1355253352),(987744,1085,1355253390),(987745,1085,1355253465),(987746,1085,1355253495),(987747,1085,1355253507),(987748,1085,1355253542),(987749,1085,1355253616),(987750,1085,1355253617),(987751,1085,1355253619),(987752,1085,1355253619),(987753,1085,1355253623),(987754,1085,1355253624),(987755,1085,1355254023),(987756,1085,1355253682),(987757,1085,1355253741),(987758,1085,1355253753),(987759,1085,1355253774),(987760,1085,1355253807),(987761,1085,1355253817),(987762,1085,1355253834),(987763,1085,1355253947),(987764,1085,1355253959),(987765,1085,1355253964),(987766,1085,1355253993),(987767,1085,1355254036),(987768,1085,1355254050),(987769,1085,1355254059),(987770,1085,1355254084),(987771,1085,1355254099),(987772,1085,1355254139),(987773,1085,1355254767),(987774,1085,1355254190),(987775,1085,1355254239),(987776,1085,1355254242),(987777,1085,1355254270),(987778,1085,1355254321),(987779,1085,1355254339),(987780,1085,1355254684),(987781,1085,1355254436),(987782,1085,1355254437),(987783,1045,1355254463),(987783,1085,1355254455),(987784,1085,1355254521),(987785,1085,1355254545),(987786,1085,1355254548),(987787,1085,1355254587),(987788,1085,1355254590),(987789,1085,1355254597),(987790,1085,1355254683),(987791,1085,1355254685),(987792,1085,1355254714),(987793,1085,1355254740),(987794,1085,1355254772),(987795,1085,1355254792),(987796,1085,1355254796),(987797,1085,1355254796),(987798,1085,1355254797),(987799,1085,1355254799),(987800,1085,1355254832),(987801,1085,1355254838),(987802,1085,1355254841),(987803,1085,1355254857),(987804,1085,1355254858),(987805,1085,1355254916),(987806,1085,1355254925),(987806,1236,1355255075),(987807,1045,1355350558),(987807,1085,1355254984),(987808,1085,1355255036),(987809,1085,1355255064),(987810,1085,1355255093),(987811,1085,1355255095),(987812,1085,1355255120),(987813,1085,1355255140),(987814,1085,1355255182),(987815,1085,1355255186),(987816,1085,1355255194),(987817,1085,1355255215),(987818,1085,1355255257),(987819,1085,1355255287),(987820,1085,1355255336),(987821,1085,1355425057),(987822,1085,1355255415),(987823,1085,1355255591),(987824,1085,1355255437),(987825,1085,1355255462),(987826,1085,1355255493),(987827,1085,1355255496),(987828,1085,1355255533),(987829,1085,1355255563),(987830,1085,1355322487),(987831,1085,1355255608),(987832,1085,1355255622),(987833,1085,1355255641),(987834,1085,1355255641),(987835,1085,1355255657),(987836,1085,1355255696),(987837,1085,1355255701),(987838,1085,1355255702),(987839,1085,1355255719),(987840,1085,1355255759),(987841,1085,1355255916),(987842,1085,1355255928),(987843,1085,1355255930),(987844,1085,1355255941),(987845,1085,1355255981),(987846,1085,1355256038),(987847,1085,1355256039),(987848,1085,1355256059),(987849,1085,1355256109),(987850,1085,1355256112),(987851,1085,1355256113),(987852,1085,1355256238),(987853,1085,1355256131),(987854,1085,1355256139),(987855,1085,1355256158),(987856,1085,1355256199),(987857,1085,1355256275),(987858,1085,1355256276),(987859,1085,1355256368),(987860,1085,1355256378),(987861,1085,1355256384),(987862,1085,1355256446),(987863,1085,1355256457),(987864,1085,1355256493),(987865,1085,1355256497),(987866,1085,1355256507),(987867,1085,1355256512),(987868,1085,1355256549),(987869,1085,1355256571),(987870,1085,1355256597),(987871,1085,1355256606),(987872,1085,1355256647),(987873,1085,1355256657),(987874,1085,1355256675),(987875,1085,1355256713),(987876,1085,1355256717),(987877,1085,1355256733),(987878,1085,1355256760),(987879,1085,1355256838),(987880,1085,1355256772),(987881,1085,1355256788),(987882,1085,1355258041),(987883,1085,1355256819),(987884,1085,1355256836),(987885,1085,1355256865),(987886,1085,1355256891),(987887,1085,1355256901),(987888,1085,1355256909),(987889,1085,1355256963),(987890,1085,1355256994),(987891,1085,1355257058),(987892,1085,1355257109),(987893,1085,1355257136),(987894,1085,1355257155),(987895,1085,1355257159),(987896,1085,1355258080),(987897,1085,1355257247),(987898,1085,1355257274),(987899,1085,1355257322),(987900,1085,1355257351),(987901,1085,1355257360),(987902,1085,1355257378),(987903,1085,1355257381),(987904,1085,1355257417),(987905,1085,1355257441),(987906,1085,1355257448),(987907,1085,1355257454),(987908,1085,1355257483),(987909,1085,1355257522),(987910,1085,1355257562),(987911,1085,1355257562),(987912,1085,1355257564),(987913,1085,1355257611),(987914,1085,1355257638),(987915,1085,1355257663),(987916,1085,1355257685),(987917,1085,1355257746),(987918,1085,1355257798),(987919,1085,1355257799),(987920,1085,1355257804),(987921,1085,1355257847),(987922,1085,1355257862),(987923,1085,1355257878),(987924,1085,1355257898),(987925,1085,1355257912),(987926,1085,1355257948),(987927,1085,1355257960),(987928,1085,1355257971),(987929,1085,1355257982),(987930,1085,1355258020),(987931,1085,1355258066),(987932,1085,1355258085),(987933,1085,1355258086),(987934,1085,1355258122),(987935,1085,1355258124),(987936,1085,1355258147),(987937,1085,1355258194),(987938,1085,1355258206),(987939,1085,1355258218),(987940,1085,1355258226),(987941,1085,1355258274),(987942,1085,1355258311),(987943,1085,1355258325),(987944,1085,1355258325),(987945,1085,1355258335),(987946,1085,1355258348),(987947,1085,1355258385),(987948,1085,1355258403),(987949,1085,1355258426),(987950,1085,1355258455),(987951,1085,1355258499),(987952,1085,1355258512),(987953,1085,1355258514),(987954,1085,1355258523),(987955,1085,1355258537),(987956,1085,1355258541),(987957,1085,1355258559),(987958,1085,1355258602),(987959,1085,1355258609),(987960,1085,1355258647),(987961,1085,1355258669),(987962,1085,1355258704),(987963,1085,1355258732),(987964,1085,1355258756),(987965,1085,1355258788),(987966,1085,1355258797),(987967,1085,1355258800),(987968,1085,1355258803),(987969,1085,1355258825),(987970,1085,1355258826),(987971,1085,1355258852),(987972,1085,1355258870),(987973,1045,1355259203),(987973,1085,1355258884),(987974,1085,1355258909),(987975,1085,1355258932),(987976,1046,1355857520),(987976,1085,1355258933),(987977,1085,1355258987),(987978,1085,1355259018),(987979,1085,1355259022),(987980,1085,1355259251),(987981,1085,1355259061),(987982,1085,1355259121),(987983,1085,1355259127),(987984,1085,1355259128),(987985,1085,1355259132),(987986,1085,1355259183),(987987,1085,1355259263),(987988,1085,1355259267),(987989,1085,1355259268),(987990,1085,1355259271),(987991,1085,1355259321),(987992,1085,1355259444),(987993,1085,1355259361),(987994,1085,1355259393),(987995,1085,1355259401),(987996,1085,1355259428),(987997,1085,1355259444),(987998,1085,1355259459),(987999,1085,1355259466),(988000,1085,1355259479),(988001,1085,1355259483),(988002,1085,1355259493),(988003,1085,1355259497),(988004,1085,1355259498),(988005,1085,1355259502),(988006,1085,1355259511),(988007,1085,1355259531),(988008,1085,1355259564),(988009,1085,1355259623),(988010,1085,1355259624),(988011,1085,1355259641),(988012,1085,1355259646),(988013,1085,1355259653),(988014,1046,1355819605),(988014,1085,1355259661),(988015,1085,1355259693),(988016,1085,1355259731),(988017,1085,1355259741),(988018,1085,1355259745),(988019,1085,1355259774),(988020,1085,1355259807),(988021,1085,1355259856),(988022,1085,1355259926),(988023,1085,1355259966),(988024,1085,1355259994),(988025,1085,1355260007),(988026,1085,1355260016),(988027,1085,1355260019),(988028,1085,1355260059),(988029,1085,1355260071),(988030,1085,1355260108),(988031,1085,1355260119),(988032,1085,1355260145),(988033,1085,1355260151),(988034,1085,1355260160),(988035,1085,1355260172),(988036,1085,1355260186),(988037,1085,1355453278),(988038,1085,1355260295),(988039,1085,1355260307),(988040,1085,1355260461),(988041,1085,1355260472),(988042,1085,1355260510),(988043,1085,1355260530),(988044,1085,1355260611),(988045,1085,1355260634),(988046,1085,1355260660),(988047,1085,1355260666),(988048,1085,1355260749),(988049,1085,1355260783),(988050,1085,1355260794),(988051,1085,1355260821),(988052,1085,1355260866),(988053,1085,1355260951),(988054,1085,1355260951),(988055,1085,1355260953),(988056,1085,1355260958),(988057,1085,1355260974),(988058,1085,1355261036),(988059,1085,1355261064),(988060,1085,1355261102),(988061,1085,1355261129),(988062,1085,1355261148),(988063,1085,1355261160),(988064,1085,1355261179),(988065,1085,1355261187),(988066,1085,1355261200),(988067,1085,1355261216),(988068,1085,1355261249),(988069,1085,1355261255),(988070,1085,1355261290),(988071,1085,1355261299),(988072,1085,1355261332),(988074,1085,1355261397),(988075,1085,1355261401),(988075,1236,1355261938),(988076,1085,1355261448),(988077,1085,1355261424),(988078,1085,1355261436),(988079,1085,1355261520),(988080,1085,1355261535),(988081,1085,1355261548),(988082,1085,1355261700),(988083,1085,1355261758),(988084,1085,1355261767),(988085,1085,1355261774),(988086,1085,1355261834),(988087,1085,1355261909),(988088,1085,1355261912),(988089,1085,1355262062),(988090,1085,1355262129),(988091,1085,1355262154),(988092,1085,1355262155),(988093,1085,1355262159),(988094,1085,1355262197),(988095,1085,1355262226),(988096,1085,1355262236),(988097,1085,1355262257),(988098,1085,1355262315),(988099,1085,1355262315),(988100,1085,1355262331),(988101,1085,1355262344),(988102,1085,1355262483),(988103,1085,1355262392),(988104,1085,1355262422),(988105,1085,1355262424),(988106,1085,1355262470),(988107,1085,1355262483),(988108,1045,1355262505),(988108,1085,1355262492),(988109,1085,1355262624),(988110,1085,1355262713),(988111,1085,1355262732),(988112,1085,1355262747),(988113,1085,1355262760),(988114,1085,1355262797),(988115,1085,1355262801),(988116,1045,1355264001),(988116,1085,1355262836),(988117,1085,1355262845),(988118,1085,1355262885),(988119,1085,1355262934),(988120,1085,1355262990),(988121,1085,1355262994),(988122,1085,1355263018),(988123,1085,1355263024),(988124,1085,1355263073),(988125,1085,1355263081),(988126,1085,1355263107),(988127,1085,1355263108),(988128,1085,1355263116),(988129,1085,1355263123),(988130,1085,1355263126),(988131,1085,1355263156),(988132,1085,1355263195),(988133,1085,1355263212),(988134,1085,1355263240),(988135,1085,1355263258),(988136,1085,1355263279),(988137,1085,1355263291),(988138,1085,1355263356),(988139,1085,1355263452),(988140,1085,1355263418),(988141,1085,1355263428),(988142,1085,1355263511),(988143,1085,1355263519),(988144,1085,1355263533),(988145,1085,1355263533),(988146,1085,1355263572),(988147,1085,1355263594),(988148,1085,1355263612),(988149,1085,1355263656),(988150,1085,1355263658),(988151,1085,1355263676),(988152,1085,1355263702),(988153,1085,1355263749),(988154,1085,1355263746),(988155,1085,1355263767),(988156,1085,1355263780),(988157,1085,1355263790),(988158,1085,1355263821),(988159,1085,1355263974),(988160,1085,1355263983),(988161,1085,1355263932),(988162,1085,1355263953),(988163,1045,1355263970),(988163,1085,1355263956),(988164,1085,1355263961),(988165,1085,1355263985),(988166,1085,1355264050),(988167,1085,1355264100),(988168,1085,1355264164),(988169,1085,1355264182),(988170,1085,1355264221),(988171,1085,1355264280),(988172,1085,1355264314),(988173,1085,1355264342),(988174,1085,1355264424),(988175,1085,1355264448),(988176,1085,1355264508),(988177,1085,1355264516),(988178,1085,1355264557),(988179,1085,1355264581),(988180,1085,1355264581),(988181,1085,1355264639),(988182,1085,1355264602),(988183,1085,1355264631),(988184,1046,1355888648),(988184,1085,1355264644),(988185,1085,1355264655),(988186,1085,1355264675),(988187,1085,1355264702),(988188,1085,1355264766),(988189,1085,1355264784),(988190,1085,1355264816),(988191,1085,1355264817),(988192,1085,1355265020),(988193,1085,1355265021),(988194,1085,1355265050),(988195,1085,1355265070),(988196,1085,1355265071),(988197,1085,1355265076),(988198,1085,1355265103),(988199,1085,1355265117),(988200,1085,1355265143),(988201,1085,1355265146),(988202,1085,1355265146),(988203,1085,1355265189),(988204,1085,1355265266),(988205,1085,1355265318),(988206,1085,1355265322),(988207,1085,1355265399),(988208,1085,1355265410),(988209,1085,1355265479),(988210,1085,1355265495),(988211,1085,1355265499),(988212,1085,1355265520),(988213,1085,1355265525),(988214,1085,1355265577),(988215,1085,1355265594),(988216,1085,1355265598),(988217,1085,1355265611),(988218,1085,1355265662),(988219,1085,1355265760),(988220,1085,1355265784),(988221,1085,1355265823),(988222,1085,1355265824),(988223,1085,1355265842),(988224,1085,1355265998),(988225,1085,1355265886),(988226,1085,1355266033),(988227,1085,1355266037),(988228,1085,1355266462),(988229,1085,1355266212),(988230,1085,1355266247),(988231,1085,1355266281),(988232,1085,1355266283),(988233,1085,1355266322),(988234,1085,1355266462),(988235,1085,1355266365),(988236,1085,1355266373),(988237,1085,1355266397),(988238,1085,1355266401),(988239,1085,1355266483),(988240,1085,1355266504),(988241,1085,1355266621),(988242,1085,1355266652),(988243,1085,1355266677),(988244,1085,1355266681),(988245,1085,1355266777),(988246,1085,1355266783),(988247,1085,1355266798),(988248,1085,1355266871),(988249,1085,1355266879),(988250,1085,1355266893),(988251,1085,1355266909),(988252,1085,1355266946),(988253,1085,1355266954),(988254,1085,1355266955),(988255,1085,1355350517),(988256,1085,1355267114),(988257,1085,1355267120),(988258,1085,1355267172),(988259,1085,1355267188),(988260,1085,1355267254),(988261,1085,1355267258),(988262,1045,1355267283),(988262,1085,1355267269),(988263,1085,1355267273),(988264,1085,1355267291),(988265,1085,1355267299),(988266,1085,1355267311),(988267,1085,1355267348),(988268,1085,1355267360),(988269,1085,1355267383),(988270,1085,1355267404),(988271,1085,1355267414),(988272,1085,1355267505),(988273,1085,1355267491),(988274,1085,1355267566),(988275,1085,1355267601),(988276,1085,1355267605),(988277,1085,1355267707),(988278,1085,1355267710),(988279,1085,1355267715),(988280,1085,1355267732),(988281,1085,1355267763),(988282,1085,1355267784),(988283,1085,1355267792),(988284,1085,1355267818),(988285,1085,1355267852),(988286,1085,1355267912),(988287,1085,1355267936),(988288,1085,1355267957),(988289,1085,1355267972),(988290,1085,1355268006),(988291,1085,1355268020),(988292,1085,1355268050),(988293,1085,1355268071),(988294,1085,1355268110),(988295,1085,1355268130),(988296,1085,1355268142),(988297,1085,1355268205),(988298,1085,1355268209),(988299,1085,1355268217),(988300,1085,1355268259),(988301,1085,1355268279),(988302,1085,1355268611),(988303,1085,1355268389),(988304,1085,1355268400),(988305,1085,1355268405),(988306,1085,1355268406),(988308,1085,1355268476),(988309,1085,1355268513),(988310,1085,1355268563),(988311,1085,1355268592),(988312,1085,1355268602),(988313,1085,1355268628),(988314,1085,1355268628),(988315,1085,1355268672),(988316,1085,1355268727),(988317,1046,1355532713),(988317,1085,1355268734),(988318,1085,1355268744),(988319,1085,1355268763),(988320,1045,1355268806),(988320,1085,1355268801),(988321,1085,1355268961),(988322,1085,1355268829),(988323,1085,1355268904),(988324,1085,1355268955),(988325,1085,1355268991),(988326,1085,1355269009),(988327,1085,1355269041),(988328,1085,1355269171),(988329,1085,1355269180),(988330,1085,1355269181),(988331,1085,1355269254),(988332,1085,1355269264),(988333,1085,1355269269),(988334,1085,1355269278),(988335,1085,1355269308),(988336,1085,1355269340),(988337,1085,1355269349),(988338,1085,1355269404),(988339,1085,1355269435),(988340,1085,1355269445),(988341,1085,1355269534),(988342,1085,1355269505),(988343,1085,1355269513),(988344,1085,1355269553),(988345,1085,1355269578),(988346,1085,1355269578),(988347,1085,1355269587),(988348,1085,1355269702),(988349,1085,1355269610),(988350,1085,1355269621),(988351,1085,1355269643),(988352,1085,1355269654),(988353,1085,1355269658),(988354,1085,1355269696),(988355,1085,1355269701),(988356,1085,1355269755),(988357,1085,1355269756),(988358,1085,1355269827),(988359,1085,1355269828),(988360,1085,1355269865),(988361,1085,1355269921),(988362,1085,1355269928),(988363,1085,1355270016),(988364,1085,1355270035),(988365,1085,1355270042),(988366,1085,1355270106),(988367,1085,1355270117),(988368,1085,1355270126),(988369,1085,1355270207),(988370,1085,1355270322),(988371,1085,1355270375),(988372,1046,1355270778),(988372,1085,1355270441),(988373,1085,1355270471),(988374,1085,1355270486),(988375,1085,1355270535),(988376,1085,1355270621),(988377,1085,1355270630),(988378,1085,1355270630),(988379,1085,1355270673),(988380,1085,1355270707),(988381,1085,1355270715),(988382,1085,1355270765),(988383,1085,1355270757),(988384,1085,1355270872),(988385,1085,1355270890),(988386,1085,1355270910),(988387,1045,1355270942),(988387,1085,1355270924),(988388,1085,1355270943),(988389,1085,1355271013),(988390,1045,1355271104),(988390,1085,1355271101),(988391,1085,1355271069),(988392,1085,1355271176),(988393,1085,1355271248),(988394,1085,1355271285),(988395,1085,1355271286),(988396,1045,1355271327),(988396,1085,1355271312),(988397,1085,1355271361),(988398,1085,1355271364),(988399,1085,1355271372),(988400,1085,1355271403),(988401,1085,1355271492),(988402,1085,1355271520),(988403,1085,1355271556),(988404,1085,1355271563),(988405,1085,1355271601),(988406,1085,1355271588),(988407,1085,1355271761),(988408,1045,1355319562),(988408,1085,1355271786),(988409,1085,1355271893),(988410,1085,1355271923),(988411,1085,1355271987),(988412,1085,1355272008),(988413,1085,1355272052),(988414,1085,1355272067),(988415,1085,1355272093),(988416,1085,1355272135),(988417,1085,1355272154),(988418,1085,1355272170),(988419,1085,1355272171),(988420,1085,1355272221),(988421,1085,1355272247),(988422,1085,1355272247),(988423,1085,1355272257),(988424,1085,1355272280),(988425,1085,1355272345),(988426,1085,1355272357),(988427,1045,1355272378),(988427,1085,1355272357),(988428,1085,1355272360),(988429,1085,1355272377),(988430,1085,1355272380),(988431,1085,1355272380),(988432,1085,1355272431),(988433,1085,1355272454),(988434,1085,1355272478),(988435,1085,1355272516),(988436,1085,1355272542),(988437,1085,1355272549),(988438,1085,1355272654),(988439,1085,1355272655),(988440,1085,1355273317),(988441,1085,1355272680),(988442,1085,1355272728),(988443,1085,1355272766),(988444,1085,1355272788),(988445,1085,1355272822),(988446,1085,1355272852),(988447,1085,1355272943),(988448,1085,1355272976),(988449,1085,1355272980),(988450,1085,1355272994),(988451,1085,1355273005),(988452,1085,1355273043),(988453,1085,1355273044),(988454,1085,1355273113),(988455,1085,1355273133),(988456,1085,1355273135),(988457,1085,1355273176),(988458,1085,1355273224),(988459,1085,1355273244),(988460,1085,1355273279),(988461,1085,1355273506),(988462,1085,1355273564),(988463,1085,1355273607),(988464,1085,1355273628),(988465,1085,1355273648),(988466,1085,1355273676),(988467,1085,1355273676),(988468,1085,1355273734),(988469,1085,1355273749),(988470,1085,1355273765),(988471,1085,1355273766),(988472,1085,1355273856),(988473,1085,1355273866),(988474,1085,1355273922),(988475,1085,1355273924),(988476,1085,1355372653),(988477,1085,1355273935),(988478,1085,1355273943),(988479,1085,1355273997),(988480,1085,1355274002),(988481,1085,1355274015),(988482,1085,1355274055),(988483,1085,1355274197),(988484,1085,1355274327),(988485,1085,1355274248),(988486,1085,1355274320),(988487,1085,1355274328),(988488,1085,1355274359),(988489,1085,1355274384),(988490,1085,1355274438),(988491,1085,1355274463),(988492,1085,1355274511),(988493,1085,1355274518),(988494,1085,1355274532),(988496,1085,1355274562),(988497,1085,1355274590),(988498,1085,1355274602),(988499,1085,1355274663),(988500,1085,1355274800),(988501,1085,1355274854),(988502,1085,1355274859),(988503,1085,1355274913),(988504,1085,1355274961),(988505,1085,1355274987),(988506,1085,1355275029),(988507,1085,1355275074),(988508,1085,1355275105),(988509,1085,1355275105),(988510,1085,1355275110),(988511,1085,1355275115),(988512,1085,1355275158),(988513,1085,1355275156),(988514,1085,1355275191),(988515,1085,1355275246),(988516,1085,1355275216),(988517,1085,1355275218),(988518,1085,1355275317),(988519,1085,1355275351),(988520,1085,1355275329),(988521,1085,1355275460),(988522,1085,1355275467),(988523,1085,1355275473),(988524,1085,1355275536),(988525,1085,1355275499),(988526,1085,1355317481),(988527,1085,1355275538),(988528,1085,1355275583),(988529,1085,1355275632),(988530,1085,1355275696),(988531,1085,1355275719),(988532,1085,1355275747),(988533,1085,1355275841),(988534,1085,1355275862),(988535,1085,1355275900),(988536,1085,1355275981),(988537,1085,1355275994),(988538,1085,1355276117),(988539,1085,1355276039),(988540,1085,1355276097),(988541,1085,1355276122),(988542,1085,1355276148),(988543,1085,1355276199),(988544,1085,1355276205),(988545,1085,1355276288),(988546,1085,1355276319),(988547,1085,1355276320),(988548,1085,1355276330),(988549,1085,1355276427),(988550,1085,1355276508),(988551,1085,1355276499),(988552,1085,1355276500),(988553,1085,1355276541),(988554,1085,1355276641),(988555,1085,1355276693),(988556,1085,1355276786),(988557,1085,1355276803),(988558,1085,1355276828),(988559,1085,1355276846),(988560,1085,1355276913),(988561,1085,1355276954),(988562,1085,1355276935),(988563,1085,1355276955),(988564,1085,1355277046),(988565,1085,1355277007),(988566,1085,1355277046),(988567,1085,1355277100),(988568,1085,1355277105),(988569,1085,1355277151),(988570,1085,1355277164),(988571,1085,1355277255),(988572,1085,1355277296),(988573,1085,1355277400),(988574,1085,1355277423),(988575,1085,1355277447),(988576,1085,1355277494),(988577,1085,1355277540),(988578,1085,1355277567),(988579,1085,1355277642),(988580,1085,1355277897),(988581,1085,1355278050),(988582,1045,1355278097),(988582,1085,1355278074),(988583,1085,1355278166),(988584,1085,1355278215),(988585,1085,1355278217),(988586,1085,1355278241),(988587,1085,1355278300),(988588,1085,1355278361),(988589,1085,1355278367),(988590,1085,1355278473),(988591,1085,1355278506),(988592,1085,1355278515),(988593,1085,1355278561),(988594,1085,1355278567),(988595,1085,1355278584),(988596,1045,1355278837),(988596,1085,1355278587),(988597,1085,1355278638),(988598,1085,1355278639),(988599,1085,1355278692),(988600,1085,1355278732),(988601,1085,1355278768),(988602,1045,1355327903),(988602,1085,1355278754),(988603,1085,1355278761),(988604,1085,1355278762),(988605,1085,1355278844),(988606,1085,1355278877),(988607,1085,1355279135),(988608,1085,1355279206),(988609,1085,1355279222),(988610,1085,1355279290),(988611,1085,1355279345),(988612,1085,1355279365),(988614,1085,1355279518),(988615,1085,1355279593),(988616,1085,1355279610),(988617,1085,1355279637),(988618,1085,1355279723),(988619,1085,1355279725),(988620,1085,1355279808),(988621,1085,1355279809),(988622,1085,1355279815),(988623,1085,1355279884),(988624,1085,1355279932),(988625,1085,1355279945),(988626,1085,1355280015),(988627,1085,1355280021),(988628,1085,1355280025),(988629,1085,1355280059),(988630,1085,1355280077),(988631,1085,1355280124),(988632,1085,1355280135),(988633,1085,1355280251),(988634,1085,1355280375),(988635,1085,1355280382),(988636,1085,1355280509),(988637,1085,1355280665),(988638,1085,1355280679),(988639,1046,1355280823),(988639,1085,1355280689),(988640,1085,1355280704),(988641,1085,1355280756),(988642,1085,1355280758),(988643,1085,1355280825),(988644,1085,1355280840),(988645,1085,1355280869),(988646,1085,1355280891),(988647,1085,1355280900),(988648,1085,1355280992),(988649,1085,1355281113),(988650,1085,1355281167),(988651,1085,1355281205),(988652,1085,1355281516),(988653,1085,1355365737),(988654,1085,1355281617),(988655,1085,1355281654),(988656,1085,1355281685),(988657,1085,1355281804),(988658,1085,1355281908),(988659,1085,1355281935),(988660,1085,1355281959),(988661,1085,1355282014),(988662,1085,1355282042),(988663,1085,1355282045),(988664,1085,1355282078),(988665,1085,1355282165),(988666,1085,1355282165),(988667,1085,1355282240),(988668,1085,1355282281),(988669,1085,1355282284),(988670,1085,1355282308),(988671,1085,1355282339),(988671,1236,1355282703),(988672,1085,1355282351),(988673,1085,1355282367),(988674,1085,1355282373),(988675,1085,1355282425),(988676,1085,1355282428),(988677,1085,1355282429),(988678,1085,1355282435),(988679,1085,1355282477),(988680,1085,1355282547),(988681,1085,1355282572),(988682,1085,1355282643),(988683,1085,1355282667),(988684,1085,1355282728),(988685,1045,1355352406),(988685,1085,1355282734),(988686,1085,1355282815),(988687,1085,1355282895),(988688,1085,1355282929),(988689,1085,1355282935),(988690,1085,1355282945),(988691,1085,1355282997),(988692,1085,1355283035),(988693,1085,1355283077),(988694,1085,1355283089),(988695,1085,1355283107),(988696,1085,1355283181),(988697,1085,1355283194),(988698,1085,1355283199),(988699,1085,1355283206),(988700,1045,1355371886),(988700,1085,1355283264),(988701,1085,1355283314),(988702,1085,1355283458),(988703,1085,1355283523),(988704,1085,1355283520),(988705,1085,1355283870),(988706,1085,1355319047),(988707,1085,1355284344),(988708,1085,1355284107),(988709,1085,1355284210),(988710,1085,1355284223),(988711,1085,1355284258),(988712,1085,1355284305),(988713,1085,1355284348),(988714,1085,1355284441),(988715,1085,1355284501),(988716,1085,1355284540),(988717,1085,1355284627),(988718,1085,1355284752),(988719,1085,1355284924),(988720,1085,1355284934),(988721,1085,1355285108),(988722,1085,1355285118),(988723,1085,1355285132),(988724,1085,1355285204),(988725,1085,1355285251),(988726,1085,1355285260),(988727,1085,1355285260),(988728,1085,1355285304),(988729,1085,1355285317),(988729,1236,1355285427),(988730,1085,1355285324),(988731,1085,1355285365),(988732,1085,1355285400),(988733,1085,1355285502),(988734,1085,1355285547),(988735,1085,1355285558),(988736,1085,1355285578),(988737,1085,1355285736),(988738,1085,1355285812),(988739,1085,1355285920),(988740,1085,1355285914),(988741,1085,1355285950),(988742,1085,1355285991),(988743,1085,1355286171),(988744,1085,1355286189),(988745,1085,1355286273),(988746,1085,1355286378),(988747,1085,1355286380),(988748,1085,1355286480),(988749,1085,1355286498),(988750,1085,1355286569),(988751,1085,1355286655),(988752,1085,1355286685),(988753,1085,1355286715),(988754,1085,1355286713),(988755,1045,1355286740),(988755,1085,1355286725),(988756,1085,1355286776),(988757,1085,1355286799),(988758,1085,1355286927),(988759,1085,1355287022),(988760,1085,1355287119),(988761,1085,1355287206),(988762,1085,1355287257),(988763,1085,1355288571),(988764,1085,1355287533),(988765,1085,1355287534),(988766,1085,1355287576),(988767,1085,1355287578),(988768,1085,1355287683),(988769,1085,1355287774),(988770,1085,1355288003),(988771,1085,1355288142),(988772,1085,1355288240),(988773,1085,1355288272),(988774,1085,1355288432),(988775,1085,1355288504),(988776,1085,1355288530),(988777,1085,1355288544),(988778,1085,1355288575),(988779,1045,1355288609),(988779,1085,1355288644),(988780,1085,1355288603),(988781,1085,1355292315),(988782,1085,1355288638),(988783,1085,1355288639),(988784,1085,1355288734),(988785,1085,1355288735),(988786,1085,1355288855),(988787,1085,1355289286),(988788,1085,1355289353),(988789,1085,1355289409),(988790,1085,1355289516),(988791,1085,1355289585),(988792,1085,1355289719),(988793,1085,1355289772),(988794,1085,1355289892),(988795,1085,1355290100),(988796,1085,1355290105),(988797,1085,1355290115),(988798,1085,1355290525),(988799,1085,1355290323),(988800,1085,1355290363),(988801,1085,1355290531),(988802,1085,1355290621),(988803,1085,1355290667),(988804,1045,1355290692),(988804,1085,1355290691),(988805,1085,1355290717),(988806,1085,1355290833),(988807,1085,1355290936),(988808,1085,1355291027),(988809,1085,1355291198),(988810,1085,1355291230),(988811,1085,1355291266),(988812,1085,1355291601),(988813,1085,1355291655),(988814,1085,1355291655),(988815,1085,1355291716),(988816,1085,1355291771),(988817,1085,1355291855),(988818,1085,1355291883),(988819,1085,1355291891),(988820,1085,1355292097),(988821,1085,1355292240),(988822,1085,1355292241),(988823,1085,1355292294),(988824,1085,1355292337),(988825,1085,1355292694),(988826,1085,1355292973),(988827,1085,1355293242),(988828,1085,1355293596),(988829,1085,1355293860),(988830,1085,1355294172),(988831,1085,1355294512),(988832,1085,1355294419),(988833,1085,1355294503),(988834,1085,1355294546),(988835,1085,1355294608),(988836,1085,1355294847),(988837,1085,1355295191),(988838,1085,1355295397),(988839,1085,1355295402),(988840,1085,1355295466),(988841,1085,1355295534),(988842,1085,1355295624),(988843,1085,1355295751),(988844,1085,1355295862),(988845,1085,1355296248),(988846,1085,1355296562),(988847,1085,1355296653),(988848,1085,1355297474),(988849,1085,1355297703),(988850,1085,1355298004),(988851,1085,1355298672),(988852,1085,1355298911),(988853,1085,1355299461),(988854,1085,1355299673),(988855,1045,1356263548),(988855,1085,1355299693),(988856,1085,1355299775),(988857,1085,1355299977),(988858,1085,1355300141),(988859,1085,1355300672),(988860,1085,1355301527),(988861,1085,1355301967),(988862,1085,1355302111),(988863,1085,1355302241),(988864,1085,1355302509),(988865,1085,1355302546),(988866,1085,1355303113),(988867,1085,1355303438),(988868,1085,1355304634),(988869,1085,1355305158),(988870,1085,1355305191),(988871,1085,1355305501),(988872,1085,1355305857),(988873,1085,1355305924),(988874,1085,1355306849),(988875,1085,1355308283),(988876,1085,1355308964),(988877,1085,1355309046),(988878,1085,1355309099),(988879,1085,1355309409),(988880,1085,1355310252),(988881,1085,1355310333),(988882,1085,1355310547),(988883,1085,1355310890),(988884,1045,1355830220),(988884,1046,1355829854),(988884,1085,1355311258),(988885,1085,1355311380),(988886,1085,1355311437),(988887,1085,1355311858),(988888,1085,1355312011),(988889,1085,1355311992),(988890,1085,1355312239),(988891,1085,1355312479),(988892,1085,1355312739),(988893,1085,1355313542),(988894,1085,1355313761),(988895,1085,1355313823),(988896,1085,1355314556),(988897,1085,1355314817),(988898,1046,1355386177),(988898,1085,1355382200),(988899,1085,1355315006),(988900,1085,1355315047),(988901,1085,1355315287),(988902,1085,1355315315),(988903,1085,1355315319),(988904,1085,1355315473),(988905,1085,1355315596),(988906,1085,1355315699),(988907,1085,1355316107),(988908,1085,1355316302),(988909,1085,1355316375),(988910,1085,1355316397),(988911,1085,1355316610),(988912,1085,1355316533),(988913,1085,1355316645),(988914,1085,1355316817),(988915,1085,1355316916),(988916,1085,1355317136),(988917,1085,1355317206),(988918,1085,1355317216),(988919,1085,1355317306),(988920,1085,1355317341),(988921,1085,1355317354),(988922,1045,1355460746),(988922,1085,1355317482),(988923,1085,1355317596),(988924,1085,1355317787),(988925,1085,1355317946),(988926,1085,1355318231),(988927,1085,1355318511),(988928,1085,1355318812),(988929,1085,1355319015),(988930,1085,1355319121),(988931,1085,1355319186),(988932,1085,1355319300),(988933,1085,1355319379),(988934,1085,1355319388),(988935,1085,1355319603),(988936,1085,1355319919),(988937,1085,1355320013),(988938,1085,1355320151),(988939,1085,1355320194),(988940,1085,1355320250),(988941,1046,1355841533),(988941,1085,1355320339),(988942,1085,1355320651),(988943,1085,1355320661),(988944,1085,1355320759),(988945,1085,1355320986),(988946,1085,1355321086),(988947,1085,1355321393),(988948,1085,1355321448),(988949,1085,1355321526),(988950,1085,1355321644),(988951,1085,1355321755),(988952,1085,1355321950),(988953,1085,1355322058),(988954,1085,1355322150),(988955,1085,1355322180),(988956,1085,1355322189),(988957,1085,1355322292),(988958,1085,1355322325),(988959,1085,1355322433),(988960,1085,1355322482),(988961,1085,1355322626),(988962,1085,1355322727),(988963,1085,1355322851),(988964,1085,1355322978),(988965,1085,1355323498),(988966,1085,1355323584),(988967,1085,1355323597),(988968,1085,1355323618),(988969,1085,1355323756),(988970,1085,1355323787),(988971,1085,1355323791),(988972,1085,1355323862),(988973,1085,1355324243),(988974,1085,1355324282),(988975,1045,1355324457),(988975,1085,1355324442),(988976,1085,1355325096),(988977,1085,1355325111),(988978,1085,1355325291),(988979,1085,1355325452),(988980,1085,1355325534),(988981,1085,1355325549),(988982,1085,1355325741),(988983,1085,1355325863),(988984,1045,1355346309),(988984,1085,1355326428),(988985,1085,1355325964),(988986,1085,1355326069),(988987,1085,1355326085),(988988,1085,1355326163),(988989,1085,1355326182),(988990,1085,1355326230),(988991,1085,1355326295),(988992,1085,1355326337),(988993,1085,1355326933),(988994,1085,1355327109),(988995,1085,1355327381),(988996,1085,1355327471),(988997,1085,1355327609),(988998,1085,1355327924),(988999,1085,1355328035),(989000,1085,1355328333),(989001,1085,1355328457),(989002,1085,1355328599),(989003,1085,1355328776),(989004,1085,1355328908),(989005,1085,1355328964),(989006,1085,1355329064),(989007,1085,1355329225),(989008,1085,1355329287),(989009,1085,1355329313),(989010,1085,1355329485),(989011,1085,1355329626),(989012,1045,1357862138),(989012,1046,1357862116),(989012,1085,1355329778),(989012,1236,1357522293),(989013,1085,1355329998),(989014,1085,1355330192),(989015,1085,1355330311),(989016,1085,1355330488),(989017,1085,1355330543),(989018,1085,1355330715),(989019,1085,1355330964),(989020,1085,1355331044),(989021,1085,1355331145),(989022,1085,1355331576),(989023,1085,1355331657),(989024,1085,1355331788),(989025,1085,1355331969),(989026,1085,1355332006),(989027,1085,1355332034),(989028,1085,1355332292),(989029,1085,1355332390),(989030,1085,1355333015),(989031,1085,1355333100),(989032,1085,1355333115),(989033,1085,1355333191),(989034,1085,1355333400),(989035,1085,1355333818),(989036,1085,1355333550),(989037,1085,1355333915),(989038,1085,1355334491),(989039,1085,1355333958),(989040,1085,1355333988),(989041,1045,1355505941),(989041,1085,1355334036),(989042,1046,1355844898),(989042,1085,1355334140),(989043,1085,1355334304),(989044,1085,1355334386),(989045,1085,1355334612),(989046,1085,1355334902),(989047,1085,1355334917),(989048,1085,1355335064),(989049,1085,1355335228),(989050,1085,1355335238),(989051,1085,1355335569),(989052,1085,1355335814),(989053,1085,1355336153),(989054,1085,1355336380),(989056,1085,1355336561),(989057,1085,1355336571),(989058,1085,1355336723),(989059,1085,1355336857),(989060,1085,1355337068),(989061,1085,1355337212),(989062,1085,1355337275),(989063,1085,1355337470),(989064,1085,1355337557),(989065,1085,1355337615),(989066,1085,1355337649),(989067,1085,1355337915),(989068,1085,1355337968),(989069,1045,1355338087),(989069,1085,1355338071),(989070,1085,1355338107),(989071,1085,1355338146),(989072,1085,1355338172),(989073,1085,1355338332),(989074,1085,1355338489),(989075,1085,1355338901),(989076,1085,1355340138),(989077,1085,1355339783),(989078,1085,1355339859),(989079,1085,1355339938),(989080,1085,1355339949),(989081,1085,1355340096),(989082,1085,1355340696),(989083,1085,1355340813),(989084,1085,1355340882),(989085,1085,1355341135),(989086,1085,1355341486),(989087,1085,1355342088),(989088,1085,1355342247),(989089,1085,1355342326),(989090,1046,1357337488),(989090,1085,1355342353),(989091,1085,1355342399),(989092,1085,1355342419),(989093,1085,1355342839),(989094,1085,1355343007),(989095,1085,1355343218),(989096,1085,1355343748),(989097,1085,1355343851),(989098,1085,1355343867),(989099,1085,1355343963),(989100,1085,1355344061),(989101,1085,1355344248),(989102,1085,1355344621),(989103,1085,1355345557),(989104,1085,1355345744),(989105,1085,1355345796),(989106,1085,1355345883),(989107,1085,1355345996),(989108,1085,1355346058),(989109,1085,1355346104),(989110,1085,1355346164),(989112,1085,1355346502),(989113,1085,1355346523),(989114,1085,1355346604),(989115,1085,1355346631),(989116,1085,1355346877),(989117,1085,1355346946),(989118,1085,1355350021),(989119,1085,1355348045),(989120,1085,1355348234),(989121,1085,1355348361),(989122,1085,1355348549),(989123,1085,1355348573),(989124,1085,1355348631),(989125,1085,1355348947),(989126,1085,1355349071),(989127,1085,1355349117),(989128,1085,1355349125),(989130,1085,1355349277),(989131,1085,1355349313),(989132,1085,1355349420),(989134,1085,1355349501),(989135,1085,1355349641),(989136,1085,1355350088),(989137,1085,1355350084),(989138,1085,1355350129),(989139,1085,1355350283),(989140,1085,1355350866),(989141,1085,1355351252),(989142,1085,1355351472),(989143,1085,1355351572),(989144,1085,1355351742),(989145,1085,1355351837),(989146,1085,1355351895),(989147,1085,1355351945),(989148,1085,1355351987),(989149,1085,1355352152),(989150,1085,1355352182),(989151,1085,1355352619),(989152,1085,1355352691),(989153,1085,1355352771),(989154,1085,1355353157),(989155,1085,1355352969),(989156,1085,1355353111),(989158,1085,1355353228),(989159,1085,1355353416),(989160,1085,1355353665),(989161,1085,1355353674),(989163,1085,1355353900),(989164,1085,1355354394),(989165,1085,1355354397),(989166,1085,1355354888),(989167,1085,1355355087),(989167,1236,1355366878),(989168,1085,1355355332),(989169,1085,1355355278),(989170,1085,1355355308),(989171,1085,1355355714),(989172,1085,1355355810),(989173,1085,1355356089),(989174,1085,1355356226),(989175,1085,1355356227),(989176,1085,1355356523),(989177,1085,1355356866),(989178,1085,1355357310),(989179,1085,1355357335),(989180,1085,1355357947),(989181,1085,1355358253),(989182,1085,1355358281),(989183,1085,1355358529),(989184,1085,1355358584),(989185,1085,1355359128),(989186,1085,1355359437),(989187,1085,1355359745),(989188,1085,1355359848),(989189,1085,1355359906),(989190,1085,1355360022),(989192,1085,1355360075),(989193,1085,1355360175),(989194,1085,1355360446),(989195,1085,1355360662),(989196,1085,1355360811),(989197,1085,1355360986),(989198,1085,1355360992),(989200,1085,1355361304),(989201,1085,1355361374),(989202,1085,1355361396),(989203,1085,1355499339),(989204,1085,1355361442),(989205,1085,1355362259),(989206,1085,1355361764),(989207,1085,1355361768),(989208,1085,1355362083),(989209,1085,1355362280),(989210,1085,1355362359),(989211,1085,1355362425),(989212,1085,1355362499),(989213,1085,1355362807),(989214,1085,1355362832),(989215,1085,1355362852),(989216,1085,1355363456),(989217,1085,1355363987),(989218,1085,1355364171),(989219,1085,1355365055),(989220,1085,1355365261),(989221,1085,1355365279),(989222,1085,1355365431),(989223,1085,1355366185),(989224,1085,1355366460),(989225,1085,1355366815),(989226,1085,1355367033),(989227,1085,1355367066),(989228,1085,1355367192),(989229,1085,1355367267),(989230,1085,1355367363),(989231,1085,1355367428),(989232,1085,1355367733),(989233,1085,1355368178),(989234,1085,1355368589),(989235,1085,1355368877),(989236,1085,1355368975),(989237,1085,1355369086),(989238,1085,1355369247),(989240,1085,1355369485),(989241,1085,1355370403),(989242,1085,1355370051),(989244,1085,1355370461),(989245,1085,1355370451),(989246,1085,1355441957),(989247,1085,1355371024),(989248,1085,1355371444),(989249,1085,1355371784),(989250,1085,1355371901),(989251,1085,1355372542),(989252,1085,1355372896),(989253,1085,1355373539),(989254,1085,1355373439),(989255,1085,1355373671),(989256,1085,1355373721),(989257,1085,1355374187),(989258,1085,1355374354),(989259,1085,1355374696),(989260,1085,1355374719),(989261,1085,1355375444),(989262,1085,1355375832),(989263,1085,1355376138),(989264,1085,1355376702),(989265,1085,1355376789),(989266,1085,1355377692),(989267,1085,1355378906),(989268,1085,1355379660),(989269,1085,1355380444),(989270,1085,1355380707),(989271,1085,1355385975),(989272,1085,1355386403),(989273,1085,1355389012),(989274,1085,1355390827),(989275,1085,1355392252),(989276,1085,1355395491),(989277,1045,1355396884),(989277,1085,1355396881),(989278,1085,1355398075),(989279,1085,1355398251),(989280,1085,1355398936),(989281,1085,1355399915),(989282,1045,1355401709),(989282,1085,1355401706),(989283,1085,1355401864),(989284,1085,1355402522),(989285,1085,1355402699),(989286,1085,1355403051),(989287,1085,1355403267),(989288,1085,1355404075),(989289,1085,1355404305),(989290,1085,1355404323),(989291,1085,1355404800),(989292,1085,1355405966),(989293,1085,1355406437),(989294,1085,1355406343),(989295,1085,1355407013),(989296,1085,1355407655),(989297,1085,1355408080),(989299,1085,1355408735),(989300,1085,1355408767),(989301,1085,1355409052),(989302,1085,1355409899),(989303,1085,1355410020),(989304,1085,1355410150),(989305,1085,1355410156),(989306,1085,1355410192),(989307,1085,1355411160),(989308,1085,1355411193),(989309,1085,1355411573),(989310,1085,1355411649),(989311,1085,1355411806),(989312,1085,1355411952),(989313,1085,1355412037),(989314,1085,1355412251),(989315,1085,1355413732),(989316,1085,1355413961),(989317,1085,1355414566),(989318,1085,1355415169),(989319,1085,1355415224),(989320,1085,1355415337),(989321,1085,1355415356),(989322,1085,1355415488),(989323,1085,1355415842),(989324,1085,1355415992),(989325,1085,1355416069),(989326,1085,1355417017),(989327,1085,1355417533),(989328,1085,1355417746),(989329,1085,1355419225),(989331,1085,1355420539),(989332,1085,1355421193),(989333,1085,1355421287),(989334,1085,1355421956),(989335,1085,1355422085),(989336,1085,1355422436),(989337,1085,1355422485),(989338,1085,1355422766),(989339,1085,1355422834),(989340,1085,1355423194),(989341,1085,1355423230),(989342,1085,1355423924),(989343,1085,1355424275),(989344,1085,1355424616),(989345,1085,1355424835),(989346,1085,1355425058),(989346,1236,1355426173),(989347,1085,1355425083),(989348,1085,1355425214),(989349,1085,1355426424),(989350,1085,1355426742),(989351,1085,1355427008),(989352,1085,1355427038),(989353,1085,1355428345),(989354,1085,1355428738),(989355,1085,1355429585),(989356,1085,1355430115),(989357,1085,1355430121),(989358,1085,1355430168),(989359,1085,1355430284),(989360,1085,1355430384),(989361,1085,1355431744),(989362,1085,1355432765),(989363,1085,1355432911),(989364,1085,1355432912),(989365,1085,1355433056),(989366,1085,1355433191),(989367,1085,1355433478),(989368,1085,1355434505),(989369,1085,1355435163),(989370,1085,1355436515),(989371,1085,1355436557),(989373,1085,1355436863),(989374,1085,1355437348),(989375,1085,1355437721),(989376,1085,1355437910),(989377,1085,1355438733),(989378,1085,1355438964),(989379,1085,1355438969),(989380,1046,1355872675),(989380,1085,1355439153),(989381,1085,1355439372),(989382,1085,1355440527),(989383,1085,1355442707),(989384,1085,1355443087),(989385,1085,1355443883),(989386,1085,1355445621),(989387,1085,1355446434),(989388,1085,1355446617),(989390,1085,1355447024),(989391,1085,1355448241),(989392,1085,1355448738),(989393,1085,1355449464),(989394,1085,1355449876),(989395,1085,1355449905),(989396,1085,1355450275),(989398,1085,1355451039),(989399,1085,1355451249),(989400,1085,1355452293),(989401,1085,1355452430),(989402,1085,1355452825),(989403,1085,1355453196),(989404,1085,1355453265),(989405,1046,1355926908),(989405,1085,1355453362),(989406,1085,1355453698),(989407,1085,1355453890),(989408,1085,1355454026),(989409,1085,1355454617),(989410,1085,1355454832),(989411,1085,1355456428),(989412,1085,1355456667),(989413,1085,1355456880),(989414,1085,1355457386),(989415,1085,1355457445),(989416,1045,1356985788),(989416,1085,1355457940),(989416,1227,1356985787),(989418,1085,1355459010),(989419,1085,1355459106),(989420,1085,1355460901),(989421,1085,1355461684),(989422,1085,1355462984),(989423,1085,1355464674),(989424,1085,1355466948),(989426,1085,1355467227),(989427,1085,1355468889),(989428,1085,1355471513),(989429,1085,1355471776),(989430,1085,1355476838),(989431,1085,1355477423),(989432,1085,1355486184),(989433,1085,1355486877),(989434,1085,1355488577),(989434,1236,1356729607),(989435,1085,1355490459),(989436,1085,1355490618),(989437,1085,1355491185),(989438,1085,1355492998),(989439,1085,1355494483),(989441,1085,1355495504),(989442,1085,1355495650),(989443,1085,1355496602),(989444,1085,1355498089),(989445,1085,1355499491),(989446,1085,1355500374),(989447,1085,1355500592),(989448,1085,1355501913),(989449,1085,1355502082),(989450,1085,1355502952),(989451,1085,1355504428),(989452,1085,1355507103),(989453,1085,1355507495),(989454,1085,1355507668),(989455,1045,1355518177),(989460,1045,1355538674),(989462,1045,1355547949),(989463,1045,1355554753),(989465,1045,1355584499),(989471,1045,1355682702),(989479,1045,1355766003),(989479,1046,1355840513),(989480,1045,1355770113),(989483,1045,1355805673),(989484,1045,1355807103),(989486,1045,1355814057),(989488,1045,1355875499),(989489,1046,1355832052),(989490,1045,1355834248),(989492,1046,1355836581),(989496,1046,1355839091),(989499,1045,1355842548),(989500,1046,1355842798),(989501,1045,1355844183),(989502,1045,1357359376),(989503,1046,1355847487),(989505,1046,1355847981),(989508,11937,1355852770),(989508,11945,1355851641),(989512,1045,1355853395),(989513,1046,1355854314),(989514,1045,1355855459),(989516,1045,1355856424),(989518,1045,1355861946),(989519,1045,1355862636),(989520,1045,1355863931),(989520,1046,1355864063),(989521,1045,1355865730),(989522,1045,1355866565),(989523,1045,1355866771),(989524,1045,1355866861),(989525,1046,1355867193),(989527,1045,1355867588),(989529,1045,1355872461),(989530,1045,1355872547),(989531,1045,1355872651),(989532,1045,1355873738),(989533,1045,1355874120),(989534,1045,1355875325),(989535,1045,1355877854),(989537,1045,1355881089),(989537,1046,1355881191),(989538,1045,1355881102),(989539,1045,1355881306),(989540,1045,1355882872),(989541,1045,1355883083),(989542,1045,1355884720),(989543,1046,1355894007),(989544,1045,1355902720),(989545,1045,1355907825),(989552,1045,1355952345),(989554,1045,1355992406),(989560,1045,1356047443),(989566,1045,1356179148),(989569,1046,1356238551),(989574,1045,1356378901),(989575,1045,1356406249),(989580,1045,1356561614),(989582,307,1356592235),(989584,1045,1357440994),(989585,1045,1356669404),(989587,1046,1356681375),(989593,1045,1356745637),(989597,1045,1356965411),(989600,1046,1357265015),(989600,11945,1357214817),(989600,11949,1357214675),(989600,11950,1357214738),(989610,1046,1357265756),(989611,1046,1357097556),(989612,1046,1357248553),(989613,1046,1357097556),(989615,1236,1357105869),(989616,1045,1357133547),(989624,1046,1357573052),(989628,1045,1357173859),(989629,1045,1357195720),(989632,1045,1357223023),(989632,1046,1357223136),(989633,1045,1357224902),(989635,1046,1357332080),(989640,1046,1357244937),(989643,1045,1357245373),(989645,1045,1357247294),(989646,1045,1357932479),(989648,1045,1357404613),(989649,1045,1357249652),(989651,1045,1357331994),(989651,1046,1357341000),(989654,1045,1357353903),(989659,1046,1357451597),(989660,1236,1357280501),(989663,1045,1357302541),(989664,1045,1357317179),(989669,1046,1357328677),(989675,1236,1357328165),(989678,1045,1357336200),(989678,1046,1357336192),(989679,1046,1357336420),(989680,1046,1357336541),(989686,1046,1357355172),(989688,1045,1357375659),(989692,1045,1357402003),(989693,1045,1357404787),(989694,1045,1357408816),(989694,1236,1357408762),(989696,1046,1357411238),(989699,1045,1357417545),(989703,1045,1357473040),(989704,1045,1357478399),(989705,1045,1357483939),(989705,1236,1357483855),(989706,1045,1357493780),(989708,1045,1357532439),(989709,1045,1357566713),(989715,1045,1357604614),(989719,1045,1357669397),(989721,1045,1357689047),(989723,1045,1357705404),(989724,1045,1357747845),(989730,1045,1357761276),(989732,1046,1357762349),(989734,1236,1357770250),(989738,1045,1357774748),(989741,1045,1357787836),(989747,1045,1357831786),(989765,1045,1357954473),(989768,1046,1357987805),(989776,1045,1358034502),(989776,1227,1358034500),(989777,1045,1358048378),(989780,1236,1358115798); +/*!40000 ALTER TABLE `history` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +CREATE DATABASE IF NOT EXISTS percona; +USE percona; +DROP TABLE IF EXISTS checksums; +CREATE TABLE `checksums` ( + `db` char(64) NOT NULL, + `tbl` char(64) NOT NULL, + `chunk` int(11) NOT NULL, + `chunk_time` float DEFAULT NULL, + `chunk_index` varchar(200) DEFAULT NULL, + `lower_boundary` text, + `upper_boundary` text, + `this_crc` char(40) NOT NULL, + `this_cnt` int(11) NOT NULL, + `master_crc` char(40) DEFAULT NULL, + `master_cnt` int(11) DEFAULT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`db`,`tbl`,`chunk`), + KEY `ts_db_tbl` (`ts`,`db`,`tbl`) +) ENGINE=InnoDB; +SET SQL_LOG_BIN=0; +INSERT INTO `checksums` VALUES ('bug918056','history',1,0.002691,'PRIMARY','21,21,1045','19468,19468,1045','411dd838',1000,'411dd838',1000,'2013-01-23 15:00:17'),('bug918056','history',2,0.019143,'PRIMARY','19514,19514,1046','989780,989780,1236','39bdd8db',11650,'39bdd8db',11650,'2013-01-23 15:00:17'),('bug918056','history',3,0.000658,'PRIMARY',NULL,'21,21,1045','0',0,'0',0,'2013-01-23 15:00:17'),('bug918056','history',4,0.000586,'PRIMARY','989780,989780,1236',NULL,'0',0,'0',0,'2013-01-23 15:00:17'); +SET SQL_LOG_BIN=1; diff --git a/t/pt-table-sync/samples/bug-918056-print.txt b/t/pt-table-sync/samples/bug-918056-print.txt new file mode 100644 index 00000000..6a3af740 --- /dev/null +++ b/t/pt-table-sync/samples/bug-918056-print.txt @@ -0,0 +1,49 @@ +DELETE FROM `bug918056`.`history` WHERE `uid`='1' AND `nid`='14' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='1' AND `nid`='1591' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='1' AND `nid`='11501' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='1' AND `nid`='12648' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='1' AND `nid`='12652' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='1045' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='1046' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='11556' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12166' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12598' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12599' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12601' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12602' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12603' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12606' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12607' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12609' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12616' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12617' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12618' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12621' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12623' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12624' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12626' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12627' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12628' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12632' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12651' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12652' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12672' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12674' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12675' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12677' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12678' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12680' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12682' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12694' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12733' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12734' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='20' AND `nid`='12738' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='21' AND `nid`='12' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='21' AND `nid`='14' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='21' AND `nid`='16' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='21' AND `nid`='191' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='21' AND `nid`='307' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='21' AND `nid`='339' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='21' AND `nid`='340' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='21' AND `nid`='901' LIMIT 1; +DELETE FROM `bug918056`.`history` WHERE `uid`='21' AND `nid`='1039' LIMIT 1; diff --git a/t/pt-table-sync/samples/bug-918056-slave.sql b/t/pt-table-sync/samples/bug-918056-slave.sql new file mode 100644 index 00000000..dd799382 --- /dev/null +++ b/t/pt-table-sync/samples/bug-918056-slave.sql @@ -0,0 +1,39 @@ +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +DROP TABLE IF EXISTS `history`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `history` ( + `uid` int(11) NOT NULL DEFAULT '0', + `nid` int(11) NOT NULL DEFAULT '0', + `timestamp` int(11) NOT NULL DEFAULT '0', + PRIMARY KEY (`uid`,`nid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +/*!40101 SET character_set_client = @saved_cs_client */; + +LOCK TABLES `history` WRITE; +/*!40000 ALTER TABLE `history` DISABLE KEYS */; +INSERT INTO `history` VALUES (1,14,1340723643),(1,1591,1325180341),(1,11501,1325182985),(1,12648,1325183126),(1,12652,1325615621),(20,1045,1327421133),(20,1046,1326826412),(20,11556,1326744741),(20,12166,1325876133),(20,12598,1322784010),(20,12599,1322784017),(20,12601,1322784014),(20,12602,1322784011),(20,12603,1322784017),(20,12606,1322783997),(20,12607,1322784003),(20,12609,1323468153),(20,12616,1323274393),(20,12617,1323468151),(20,12618,1323468153),(20,12621,1323468154),(20,12623,1323468151),(20,12624,1323468139),(20,12626,1324078562),(20,12627,1324078569),(20,12628,1324078562),(20,12632,1324078565),(20,12651,1325876176),(20,12652,1325876171),(20,12672,1325876166),(20,12674,1325693688),(20,12675,1325876176),(20,12677,1326472267),(20,12678,1325876165),(20,12680,1326472230),(20,12682,1326472270),(20,12694,1326472268),(20,12733,1326472265),(20,12734,1326472266),(20,12738,1326740335),(21,12,1334095836),(21,14,1335029191),(21,16,1347655585),(21,191,1337622606),(21,307,1345245663),(21,339,1335738908),(21,340,1337622628),(21,901,1329272552),(21,1039,1334209651),(21,1045,1356390977),(21,15077,1355862530),(21,15091,1356389282),(21,15093,1356790060),(25,1045,1357937579),(25,1046,1357662059),(54,14842,1356709584),(54,15068,1355337180),(54,15070,1355431148),(54,15075,1355771791),(54,15080,1355936015),(54,15087,1356920353),(54,15089,1356368911),(54,15090,1356920381),(54,15091,1356537468),(54,15092,1356626267),(54,15093,1356979080),(54,15095,1357323810),(54,15097,1357310198),(54,15098,1357323824),(54,15107,1357853282),(54,15108,1357822348),(54,15110,1357851189),(59,1045,1357066507),(59,1227,1355840257),(62,1045,1357949159),(62,1046,1357663553),(62,4565,1355352089),(65,1045,1357764409),(67,1045,1357930070),(67,1046,1355750176),(67,1266,1355495161),(74,1046,1357662795),(105,1045,1357254374),(105,1046,1357254296),(106,1045,1355763248),(120,1045,1356798982),(120,1227,1356798980),(128,1046,1355498580),(143,1046,1357337808),(149,1045,1357238805),(159,1045,1357752547),(159,1046,1357665158),(174,1045,1357679824),(174,1046,1357679071),(174,15108,1357766878),(175,15097,1357325775),(187,1045,1357324089),(187,1046,1357324096),(243,14,1356393835),(243,1045,1356683074),(244,1046,1355727280),(251,1046,1357337118),(256,1045,1358088842),(259,1045,1357075192),(259,1046,1356007577),(264,1045,1357327207),(264,1227,1357327205),(264,1236,1357327180),(288,1046,1356443078),(289,1045,1357913495),(292,1046,1355414251),(297,1045,1357749582),(300,1045,1357335518),(305,1046,1357336628),(308,1085,1355358490),(309,1045,1357258403),(309,1085,1355272403),(317,1045,1357351288),(325,1045,1357764751),(325,1046,1357337560),(325,1236,1357224022),(359,1045,1357932214),(374,1045,1357952255),(399,1045,1357340847),(399,1046,1357340845),(413,1046,1356389902),(424,1045,1355266998),(424,1046,1357339972),(424,11496,1355245935),(424,11945,1356985024),(424,11950,1357584209),(424,15105,1357680908),(434,1236,1355508145),(437,1045,1357964301),(454,1046,1357333076),(454,1236,1357675386),(467,1045,1357844178),(467,1046,1357058973),(467,1085,1355254593),(470,1045,1358025068),(538,1045,1357323914),(594,1085,1355239973),(594,1236,1357249373),(608,1045,1355835306),(620,1085,1355235210),(629,1045,1355776916),(659,1045,1357962784),(692,1045,1357933867),(731,1045,1357355342),(737,1045,1357751581),(795,1045,1355783770),(795,1046,1357329859),(812,1045,1358050502),(822,1045,1357324207),(822,1227,1357324204),(835,1045,1357912747),(837,1045,1357768710),(841,1040,1357337094),(841,1045,1357337094),(841,1046,1357337063),(884,1045,1357932955),(896,1045,1358023011),(899,1045,1357942562),(914,1045,1358124965),(925,1045,1358008745),(930,1236,1355830584),(946,1045,1357908733),(964,1045,1357828765),(967,1045,1357328027),(970,1045,1357520222),(974,1045,1357520392),(979,1045,1358100819),(981,1046,1357337252),(994,1045,1357329322),(1014,1046,1357338393),(1018,1045,1357838644),(1018,1046,1357325164),(1038,1045,1355810285),(1068,1045,1358004694),(1089,1045,1357949393),(1091,1045,1358093921),(1093,1046,1357250453),(1100,1045,1357737248),(1107,1046,1357338122),(1136,1045,1358103728),(1136,1227,1357921864),(1138,1046,1357338689),(1139,1045,1357354016),(1176,1045,1358119296),(1176,1227,1357988525),(1191,1236,1357942843),(1197,1045,1357080039),(1197,1046,1357338168),(1197,1227,1357080039),(1197,1236,1357080032),(1198,1046,1357340172),(1201,1085,1355244720),(1206,1046,1356431705),(1210,1045,1358084588),(1221,1085,1355241319),(1256,1046,1358163447),(1321,1045,1357327914),(1337,1046,1355689409),(1340,1045,1358099346),(1340,1236,1357512667),(1343,1045,1357927779),(1354,1045,1357663844),(1401,1046,1357339965),(1405,1045,1358055553),(1405,1046,1357935118),(1410,1045,1357329332),(1410,15106,1357769075),(1467,1045,1357960693),(1499,1045,1357074014),(1510,1085,1355256156),(1520,1045,1357645128),(1520,1227,1357641928),(1520,1236,1357644899),(1604,1045,1357749613),(1626,1045,1356985157),(1640,1045,1357234823),(1643,1046,1357337085),(1648,1045,1357671787),(1658,1236,1355872488),(1666,1045,1357682842),(1668,1045,1357933107),(1668,1085,1355243910),(1784,1045,1357960104),(1784,1236,1357785209),(1820,1045,1357598059),(1827,1045,1357937023),(1847,1085,1355337249),(1891,1046,1357341042),(1905,1045,1357391081),(1905,1085,1355244740),(1909,1045,1358111972),(1909,1046,1357855319),(1909,1227,1355628676),(1915,1045,1357231460),(1933,1046,1357336423),(1967,1045,1357605511),(1972,1046,1357241548),(1976,1045,1357968515),(1978,1045,1357619518),(1980,1046,1358076861),(1981,1236,1356111049),(2015,1045,1357281779),(2015,1227,1357281778),(2018,1046,1357326899),(2040,1085,1355246910),(2049,1045,1357687329),(2058,1046,1357340351),(2061,1045,1357944806),(2061,1046,1357340464),(2079,1045,1357352724),(2079,1236,1357352728),(2083,1045,1357584295),(2107,1045,1357773329),(2143,1045,1357623158),(2182,1045,1357964610),(2184,1045,1357085530),(2184,1227,1357085499),(2193,1045,1357965765),(2198,1045,1357268337),(2223,1045,1358132951),(2223,1227,1357278095),(2259,1046,1356643652),(2262,1046,1356269860),(2271,1045,1358095419),(2279,1045,1355938722),(2286,1046,1355469256),(2289,1085,1355237184),(2312,1045,1357264420),(2317,1085,1355275914),(2318,1046,1356612100),(2328,1045,1357327811),(2330,1085,1355323629),(2350,1045,1358007629),(2370,1236,1357420725),(2397,1045,1357353835),(2411,1045,1357609059),(2423,1045,1357933913),(2427,1046,1357339432),(2455,1045,1357548003),(2463,1046,1357276433),(2465,1046,1357338132),(2485,1046,1356904286),(2485,1085,1355334761),(2518,1236,1356707976),(2522,1045,1357793674),(2538,1045,1357267442),(2543,1085,1355254304),(2561,1085,1355248186),(2587,1045,1355787098),(2618,1045,1355629436),(2618,1085,1355241036),(2618,1227,1355629436),(2618,1236,1356049718),(2624,1045,1357353965),(2629,1045,1356726368),(2629,1227,1356726367),(2634,1045,1357575100),(2647,1045,1356690281),(2647,1046,1356777159),(2652,1045,1358124796),(2656,1045,1358125904),(2664,1085,1355316722),(2689,1045,1357922586),(2689,1227,1357922583),(2698,1046,1357332436),(2702,1045,1355581198),(2708,1046,1357132299),(2717,1046,1358082531),(2721,1045,1358092575),(2721,1046,1357341491),(2751,1045,1357631439),(2752,1045,1358148679),(2771,1085,1355241299),(2773,1046,1357338130),(2804,1045,1357088269),(2831,1045,1357260082),(2844,1046,1356441364),(2856,1045,1357526234),(2861,1045,1357954064),(2868,1046,1356717987),(2895,1045,1357779884),(2895,1046,1357779828),(2895,1227,1357779883),(2895,1236,1356547854),(2896,1045,1357328030),(2906,1045,1357348045),(2906,1046,1357964957),(2906,1236,1357399873),(2907,1045,1355855182),(2936,1046,1358016024),(2939,1045,1355512254),(2939,1227,1355512254),(2952,1045,1357685546),(2952,1227,1357685545),(2975,1045,1357682283),(2980,1045,1357335535),(2987,1045,1358011826),(3016,1046,1357337967),(3033,1045,1357646608),(3039,1236,1357667878),(3050,1045,1358005753),(3074,1236,1357500614),(3076,1045,1357933142),(3076,1046,1357328824),(3086,1045,1357948121),(3087,1045,1357930401),(3092,1045,1357261050),(3093,1045,1357932436),(3152,1045,1357933431),(3154,1045,1355781710),(3154,1046,1357340070),(3168,1045,1355577002),(3168,1227,1355577001),(3173,1045,1355865973),(3178,1046,1357336444),(3195,1046,1357249333),(3199,1042,1357336935),(3199,1046,1357336936),(3200,1045,1357353200),(3226,1045,1357087106),(3228,1045,1357676384),(3238,1045,1357347374),(3238,1236,1357849373),(3249,1045,1357943868),(3275,1045,1358141158),(3283,1045,1357347564),(3293,1045,1355508619),(3295,1045,1356040073),(3307,1085,1355263569),(3314,1045,1355809141),(3316,1046,1357336463),(3320,7752,1357947872),(3326,1045,1357778618),(3371,1045,1357282950),(3373,1045,1357477115),(3375,11950,1357420670),(3395,1085,1355175022),(3425,1045,1358129585),(3427,1045,1357952965),(3456,1085,1355369239),(3463,1046,1355726997),(3494,1045,1357937672),(3494,1085,1355266877),(3523,1045,1358007508),(3530,1045,1357307944),(3565,1045,1358105949),(3565,1046,1357003302),(3565,1227,1358105949),(3574,1046,1357338118),(3595,1085,1355282329),(3611,1045,1358088620),(3619,1046,1357337515),(3631,1045,1357617499),(3641,1045,1355840944),(3641,1085,1355316052),(3657,1085,1355248766),(3663,1045,1355175684),(3663,1227,1355175683),(3687,1045,1357248005),(3687,1227,1357248004),(3688,1046,1357664522),(3747,1045,1357622645),(3750,1045,1357080677),(3753,1046,1357340369),(3769,1045,1357040918),(3792,15106,1357865551),(3810,1045,1357619187),(3810,1085,1355257504),(3812,1046,1357335893),(3830,1045,1357753623),(3835,1046,1356786937),(3897,1045,1358099059),(3897,1227,1357420136),(3897,1236,1357420149),(3957,1045,1356204181),(3961,15072,1355507103),(3965,1085,1355262163),(3984,1236,1355874969),(4040,1045,1358045888),(4047,1045,1357353890),(4060,1046,1356437805),(4083,1046,1357337759),(4094,1085,1355235473),(4110,1045,1357142222),(4116,1045,1357950510),(4127,1045,1358099990),(4133,1046,1357178238),(4133,1085,1355334109),(4133,1236,1355440614),(4149,1085,1355279787),(4175,1045,1357946276),(4181,1045,1357696852),(4181,1236,1357701857),(4186,1045,1358020014),(4202,1045,1357549673),(4213,1236,1355810482),(4223,1045,1357970842),(4223,1046,1357880835),(4223,1227,1357970840),(4246,1045,1357667699),(4247,1046,1355747196),(4274,1046,1357906155),(4284,1085,1355235412),(4290,1045,1357224727),(4293,1045,1357938966),(4307,1046,1357256016),(4309,1046,1356087794),(4331,1045,1357359786),(4336,1045,1357619723),(4344,1085,1355238389),(4374,1085,1355244112),(4408,1085,1355257741),(4408,1236,1357935995),(4412,1045,1357933725),(4416,1046,1357244560),(4418,1085,1355372204),(4466,1045,1357926804),(4467,1045,1357926849),(4484,1046,1358159475),(4490,1045,1355510742),(4505,1045,1357291997),(4511,1085,1355275485),(4518,1085,1355242509),(4529,1045,1357948107),(4531,1045,1357326406),(4540,12263,1358112045),(4544,1085,1355252214),(4568,1236,1357086486),(4572,1045,1357534414),(4587,1236,1355178796),(4604,1046,1357323654),(4625,1045,1358008425),(4648,1046,1356641192),(4660,1045,1356125008),(4681,1045,1357939675),(4684,1045,1355251344),(4684,1085,1355251366),(4690,1045,1357931422),(4708,1045,1357933024),(4739,1045,1357769458),(4745,1045,1356147427),(4745,1046,1357738546),(4745,1085,1355293639),(4791,1045,1356122911),(4791,1227,1356122838),(4813,1045,1356367047),(4820,1046,1355477643),(4821,1045,1357694070),(4833,1045,1357980015),(4839,1045,1357998299),(4892,1045,1357665876),(4899,1236,1357747941),(4903,1045,1357353039),(4920,1045,1357225224),(4951,1045,1357011659),(4968,1045,1357758330),(4968,1046,1357243756),(4970,1045,1357936269),(4975,1045,1357247467),(4975,1085,1355312275),(4978,1045,1358099952),(4978,1046,1355268824),(4978,1236,1357082945),(4982,1046,1357337189),(4984,1045,1357945943),(5025,1045,1357573419),(5025,1227,1357573417),(5060,1045,1357935464),(5089,1046,1355699233),(5089,1085,1355253757),(5110,1045,1357961983),(5113,1236,1357273391),(5115,1045,1357342063),(5117,1045,1357933453),(5117,1085,1355237606),(5161,1045,1358026078),(5161,1227,1357863401),(5161,1236,1358025883),(5165,1046,1356439529),(5173,1046,1357336782),(5178,1045,1357249510),(5207,1085,1355238004),(5210,1046,1357014515),(5238,1045,1355850166),(5253,1045,1355183296),(5268,1045,1357303593),(5268,1227,1357303592),(5271,1045,1357335456),(5286,1045,1357935627),(5286,1046,1357341240),(5298,1045,1358031294),(5300,1045,1356170656),(5300,1227,1356170655),(5300,1236,1356170819),(5363,1045,1355243923),(5363,1046,1357339940),(5363,1236,1357417581),(5372,1236,1357716353),(5374,1045,1358042362),(5374,1046,1357205149),(5374,1227,1357060759),(5388,1045,1357387963),(5388,1227,1357387963),(5388,1236,1357388038),(5397,1045,1355553803),(5397,1085,1355235732),(5431,1085,1355235883),(5442,1045,1357353931),(5449,1085,1355182618),(5474,1045,1356727776),(5475,1045,1357408549),(5476,1045,1357359181),(5503,1045,1357750923),(5520,1045,1357972133),(5534,1045,1357245742),(5567,1045,1358003273),(5590,1045,1357957201),(5592,1085,1355256571),(5613,1045,1357667007),(5613,1046,1356718675),(5613,1236,1356799855),(5614,1045,1357630262),(5618,1085,1355239119),(5633,1046,1357257872),(5682,1045,1357955848),(5708,1046,1357333999),(5712,1045,1357948117),(5761,1236,1357890789),(5797,1045,1357946783),(5808,1045,1357246185),(5871,1045,1355502086),(5900,1085,1355334631),(5934,1045,1355272512),(5945,1045,1357616040),(5977,1045,1357696552),(5982,1045,1357933606),(6067,1085,1355257179),(6071,1045,1357521814),(6145,1046,1356116717),(6156,1045,1358002805),(6175,1236,1357163763),(6190,1046,1357340933),(6222,1045,1358155211),(6248,1045,1357951485),(6248,1227,1357951484),(6271,7253,1357334733),(6275,1085,1355184800),(6281,1045,1355181901),(6294,11945,1357936189),(6294,11951,1357936159),(6317,1045,1357258517),(6375,1046,1357336911),(6400,1085,1355251812),(6447,1045,1357848004),(6491,1045,1358148188),(6503,1045,1357849843),(6516,1236,1357080869),(6555,1045,1355279621),(6605,1045,1357978106),(6611,1085,1355273342),(6627,1085,1355241427),(6654,1045,1357937282),(6694,1045,1355783080),(6694,1227,1355783079),(6705,1085,1355354612),(6732,1046,1357336957),(6742,1085,1355242959),(6757,1045,1357457280),(6757,1046,1356163732),(6757,1227,1357457278),(6757,1236,1357457236),(6792,1085,1355278753),(6801,1085,1355260220),(6802,1045,1355576880),(6802,1046,1357340187),(6804,1046,1357340332),(6850,1045,1357327704),(6852,1236,1357137857),(6909,1045,1357265137),(6943,1085,1355244903),(6944,1045,1355852943),(6972,1045,1357663880),(6973,1045,1358102628),(7018,1045,1357359471),(7020,1045,1357398872),(7020,1227,1357398870),(7063,1045,1357367027),(7125,1045,1358030371),(7147,1045,1357086759),(7191,1046,1357172319),(7205,1045,1357945961),(7300,1236,1357663749),(7301,1042,1357341011),(7301,1045,1357349840),(7301,1046,1357341024),(7305,1236,1357080297),(7379,1046,1356307066),(7412,1046,1357310396),(7420,1046,1357249326),(7483,1045,1356115215),(7561,1085,1355248387),(7603,1236,1355241789),(7690,1046,1357323656),(7729,1045,1355259143),(7734,1046,1355691858),(7783,1045,1357345644),(7817,1045,1357933644),(7996,1085,1355238435),(8147,1045,1355507006),(8278,1046,1357592473),(8331,1045,1358124426),(8347,1045,1355510097),(8432,1045,1358019862),(8486,1085,1355501954),(8500,1045,1357954983),(8562,1040,1357337939),(8562,1045,1357337940),(8562,1046,1357337873),(8613,1045,1355508436),(8613,1085,1355288209),(8649,1045,1357607058),(8655,1045,1357308253),(8655,1227,1357308194),(8655,5071,1358094337),(8660,1045,1357966399),(8699,1046,1357217964),(8719,1045,1357244863),(8791,1045,1357262696),(8885,1085,1355236274),(8888,1045,1357949771),(8923,1045,1357309975),(8924,1045,1357327779),(8971,1085,1355247996),(8996,1045,1357358016),(9000,1085,1355287920),(9030,1045,1357933905),(9076,1045,1357347826),(9116,1085,1355290399),(9117,1045,1355855479),(9176,1046,1355311663),(9186,1046,1357336950),(9294,1045,1357964256),(9310,1046,1357337989),(9317,1045,1355859621),(9410,1045,1357946865),(9410,1085,1355235433),(9484,1085,1355317053),(9573,1085,1355235837),(9599,1046,1357993880),(9599,1236,1357303568),(9634,1045,1357697979),(9642,1045,1357335514),(9688,1046,1357552289),(9694,1045,1357249633),(9726,1045,1355839800),(9739,1045,1355859555),(9803,1085,1355248340),(9813,1046,1355864469),(9819,1045,1357934417),(9857,1085,1355237940),(9864,1045,1358021920),(9864,1046,1357341232),(9889,1045,1355859861),(9926,1046,1357132296),(9946,1085,1355355009),(9990,1045,1356541884),(10033,1045,1357076738),(10033,1085,1355236085),(10118,1045,1358086825),(10120,1045,1357327939),(10171,1085,1355244001),(10208,1045,1357854159),(10380,1046,1357339574),(10404,1045,1357393488),(10438,1085,1355243277),(10466,1045,1356131814),(10477,1045,1357244856),(10532,1085,1355243848),(10560,1045,1355843437),(10638,1046,1357340429),(10652,1085,1355252286),(10733,1045,1357945792),(10795,1046,1356845377),(10816,1046,1357326750),(10852,1045,1355818701),(10879,1045,1357931911),(10940,1045,1357499959),(11074,1045,1357755898),(11120,1236,1355520841),(11189,1045,1357335482),(11222,1045,1357935810),(11241,1045,1357246635),(11251,1046,1357336733),(11253,1045,1357077451),(11301,1045,1357602851),(11359,1045,1357933871),(11359,1236,1355806512),(11387,1045,1357932161),(11387,1046,1357324066),(11388,1045,1357822124),(11388,1046,1357822079),(11422,1085,1355235755),(11531,1085,1355243719),(11541,1046,1357340200),(11541,1236,1356888800),(11543,1045,1358044197),(11545,1046,1357999768),(11563,1085,1355252821),(11577,1045,1357936082),(11624,1046,1357249321),(11636,15080,1355937886),(11646,1046,1357339690),(11659,1045,1357347778),(11695,1045,1357959081),(11708,1045,1358082885),(11763,1045,1355446238),(11772,1045,1355787288),(11782,1045,1357305132),(11864,1045,1357933595),(11999,1045,1357327820),(12049,1045,1357093926),(12062,1045,1356122385),(12098,1236,1355846813),(12110,1045,1357956955),(12120,1045,1357346731),(12198,1045,1357509193),(12198,2553,1356379639),(12224,1085,1355237871),(12232,1045,1357694621),(12237,1045,1357904449),(12324,1045,1357577524),(12354,1045,1357245263),(12368,1046,1357326897),(12380,1046,1355570130),(12427,1045,1357933049),(12438,1046,1357339920),(12457,1085,1355241126),(12473,1045,1358000625),(12473,1046,1357327779),(12476,1236,1355540470),(12519,1046,1357339351),(12544,1045,1357081862),(12560,1045,1358004904),(12591,1046,1357331301),(12618,1045,1357935237),(12621,1045,1355217550),(12622,1045,1357595008),(12640,1045,1357589108),(12640,1046,1357336284),(12710,1085,1355247072),(12748,1045,1357245151),(12761,1085,1355294551),(12800,1045,1357946007),(12867,1045,1357949548),(12916,1045,1357913121),(12919,1045,1357767692),(12940,1045,1357700998),(12953,1046,1357938594),(12973,1045,1355870092),(12978,1046,1357336978),(13010,1045,1357346342),(13020,1046,1357339945),(13054,1042,1357086621),(13054,1045,1357086474),(13060,1046,1357338250),(13158,1045,1357943165),(13168,1045,1358093865),(13268,1046,1355568775),(13274,1045,1357425578),(13274,1046,1356939369),(13311,1045,1355956075),(13311,1046,1357340464),(13315,1045,1357944902),(13373,14,1355264549),(13373,1045,1355845028),(13373,1085,1355272387),(13402,1045,1357328007),(13418,1046,1357340861),(13440,1085,1355245227),(13484,1085,1355262320),(13488,1045,1358098386),(13490,1085,1355294019),(13528,1085,1355237506),(13596,1085,1355240601),(13610,1045,1357938582),(13625,1045,1357263991),(13730,1045,1356123537),(13761,1045,1356125188),(13783,1045,1357328067),(13834,1045,1357938594),(13842,1045,1357933936),(13842,1085,1355237900),(13858,1046,1355675019),(13859,1045,1357935956),(13890,1045,1356728615),(13890,1085,1355264855),(13916,1045,1357947034),(13930,1046,1357341384),(13941,1046,1357338948),(13956,1045,1357946928),(13957,1045,1357249335),(13994,1045,1357324483),(14013,1046,1357339285),(14025,1236,1356979056),(14035,1045,1357325757),(14047,1046,1357337613),(14050,1045,1357325249),(14116,1045,1357946929),(14176,1045,1357245623),(14202,1045,1357352190),(14216,1085,1355243490),(14223,1085,1355247305),(14292,1046,1357339859),(14292,1236,1357350439),(14293,1046,1357322983),(14329,1085,1355178931),(14382,1045,1357959485),(14437,15093,1356734687),(14462,1046,1357338518),(14475,1045,1355272646),(14503,1085,1355339582),(14539,1045,1356467284),(14539,1046,1355616645),(14539,1227,1356467283),(14542,1045,1357664183),(14574,1046,1357255885),(14606,1045,1357336123),(14606,1046,1357336071),(14614,1045,1357937234),(14635,1045,1357335738),(14636,1236,1357078498),(14697,15094,1357268148),(14708,1045,1357263790),(14763,1085,1355244382),(14775,1085,1355280971),(14809,1085,1355240855),(14826,1045,1357590220),(14865,1045,1357966267),(14871,1045,1357874019),(14871,1085,1355246765),(14872,1045,1357959959),(14872,1236,1355626426),(14937,1045,1357245307),(14942,1046,1357336054),(14979,1236,1357330429),(15039,1085,1355246375),(15040,1045,1357346892),(15042,1045,1357074522),(15062,1045,1355235010),(15095,1045,1357351118),(15106,1085,1355270392),(15109,1045,1357951989),(15126,1045,1357408646),(15126,1227,1357408645),(15132,1236,1357174817),(15173,1085,1355237757),(15198,1045,1357249431),(15247,1046,1356754762),(15264,1045,1357668275),(15303,1045,1357957078),(15308,1045,1357939553),(15308,1046,1357336459),(15312,1046,1355176339),(15346,1045,1357359888),(15413,1085,1355249891),(15415,1046,1357323647),(15423,1085,1355196402),(15458,1045,1355233020),(15481,1045,1358017539),(15506,1045,1357356494),(15510,1045,1357954160),(15530,1045,1357263994),(15546,1042,1357339726),(15546,1046,1357339727),(15574,1045,1357342518),(15574,1227,1357342516),(15574,1236,1357342564),(15606,1045,1357245127),(15641,1045,1355181512),(15734,1045,1357348147),(15743,1045,1355868278),(15743,1046,1357338500),(15746,1045,1357956266),(15761,1045,1357332325),(15819,1085,1355236174),(15864,1046,1356567562),(15869,1045,1357932390),(15908,1045,1357954671),(15919,1085,1355237242),(16141,1046,1355821326),(16147,1045,1357950909),(16147,1046,1356690343),(16180,1045,1357624205),(16217,1045,1357337110),(16217,1046,1357336934),(16233,1045,1357246183),(16304,1046,1356252471),(16329,1045,1357980396),(16333,1045,1357365574),(16349,1045,1357920441),(16358,1045,1357675926),(16482,1045,1357364787),(16482,1227,1357364664),(16482,1236,1357364780),(16486,1085,1355344801),(16528,1045,1357346622),(16530,1046,1355909071),(16561,1085,1355260709),(16567,1045,1357324340),(16617,1046,1356593947),(16635,1045,1357929835),(16661,1042,1357336955),(16661,1046,1357336956),(16700,1046,1357323709),(16723,1045,1358091198),(16758,1085,1355256893),(16797,1046,1357663632),(16846,1046,1356352142),(16847,1045,1357640302),(16847,1046,1357640157),(16848,1045,1357863253),(16880,1045,1358162676),(16891,1045,1357249468),(16912,1045,1357125925),(16935,1085,1355507240),(16944,1045,1357931970),(16971,1045,1357377141),(17013,1085,1355439728),(17026,1046,1357329000),(17056,1085,1355262790),(17091,1085,1355249618),(17123,1045,1355507923),(17131,1045,1357999371),(17159,1045,1357076842),(17277,1045,1357929845),(17325,1045,1355848439),(17341,1045,1357085068),(17369,1046,1357339598),(17385,1046,1358018377),(17433,1236,1355183223),(17467,1046,1357340116),(17481,1046,1357338457),(17626,1046,1356438541),(17654,1085,1355260147),(17782,1046,1355991473),(17791,1046,1357216782),(17792,1045,1358111473),(17801,1085,1355242224),(17808,1046,1357336755),(17901,1236,1357333237),(17914,1045,1357327863),(17961,1046,1357329831),(17967,1085,1355277755),(17990,1045,1355854826),(18064,1085,1355508493),(18074,1085,1355259046),(18343,1045,1357600389),(18375,1045,1357442716),(18405,1045,1357353133),(18480,1045,1357942391),(18524,1045,1357260956),(18550,1045,1358005290),(18561,1236,1355549262),(18600,1045,1357416584),(18621,1046,1357339109),(18621,1085,1355239332),(18627,1085,1355273391),(18631,1045,1357341326),(18631,1046,1357341321),(18713,1045,1358002552),(18743,1045,1355548269),(18751,1045,1357599221),(18751,1236,1356120645),(18763,1046,1357336904),(18763,1085,1355189279),(18790,1045,1357499140),(18828,1045,1358126392),(18828,1046,1355639551),(18889,1046,1355176340),(18897,1045,1358093664),(18897,1085,1355277669),(18929,1045,1357327936),(18959,1045,1357935777),(18981,1045,1358049589),(18987,1045,1355860953),(19008,1085,1355327618),(19009,1045,1357329311),(19015,1085,1355238692),(19052,1046,1357247078),(19117,1045,1357335492),(19171,1045,1357742278),(19174,1045,1355852476),(19177,1046,1357337057),(19202,1045,1357358751),(19326,1046,1355494870),(19350,1045,1357495502),(19362,1045,1358021592),(19362,1085,1355246496),(19370,10908,1356288634),(19378,1046,1357336898),(19440,1046,1357132307),(19446,1045,1358150351),(19455,1046,1357340536),(19468,1045,1357691688),(19514,1046,1357339213),(19539,1045,1357522600),(19596,1045,1357130596),(19623,1236,1357671324),(19685,1045,1358014529),(19689,1045,1357327824),(19716,1045,1358006929),(19716,1227,1358006927),(19778,1045,1357335827),(19793,1085,1355236839),(19885,1045,1357136202),(19901,1085,1355279404),(19926,1045,1358022008),(19931,1045,1357335780),(20055,1085,1355248158),(20166,1046,1357338120),(20194,1046,1357338717),(20227,1045,1355786773),(20256,1046,1357377709),(20302,1045,1358025122),(20332,1045,1357313471),(20382,1085,1355247742),(20388,1085,1355236624),(20417,1045,1357347374),(20417,1236,1357346958),(20487,1046,1357340867),(20529,1045,1357933162),(20639,1045,1355273094),(20677,1045,1357335649),(20703,1045,1358124161),(20703,1046,1356242074),(20855,1046,1357337768),(20928,1045,1357939427),(20956,1046,1357472431),(21046,1045,1357407116),(21070,1046,1356709226),(21071,1045,1357370168),(21074,1046,1356277564),(21074,1236,1355809204),(21135,1046,1357724702),(21171,1045,1355253882),(21171,1227,1355253881),(21179,1045,1357310036),(21221,1045,1357258743),(21303,1236,1357309014),(21378,1046,1357340682),(21416,1045,1357931789),(21611,1045,1357664911),(21611,1085,1355249028),(21666,1045,1355856796),(21684,1045,1357353099),(21684,1227,1357353098),(21705,1046,1355331000),(21705,15068,1355345919),(21705,15069,1355428584),(21705,15106,1357937425),(21794,1085,1355245813),(21819,1046,1357839332),(21845,1045,1355872283),(21845,1046,1357340350),(21941,1045,1357749679),(21950,1236,1357715955),(21966,1045,1357749757),(22011,1045,1357099050),(22033,1045,1357933403),(22061,1045,1358129532),(22196,1045,1357335550),(22306,1045,1357694544),(22335,1046,1357338119),(22356,1046,1357336080),(22410,1045,1355861631),(22410,1227,1355861629),(22455,1045,1357253426),(22481,1046,1357339703),(22482,1042,1357336274),(22482,1046,1357336418),(22506,1045,1357518348),(22518,1046,1357336206),(22535,1045,1355864362),(22595,1085,1355263707),(22598,1040,1357336671),(22598,1042,1357336656),(22598,1045,1357336672),(22598,1046,1357336802),(22618,1085,1355238364),(22623,1045,1357933774),(22627,1046,1357337182),(22683,1045,1355835899),(22699,1045,1357017201),(22699,1227,1357017200),(22705,1045,1355867118),(22708,1046,1357324133),(22733,1046,1357338561),(22825,1045,1357938632),(22832,1236,1356144656),(22846,1046,1357336673),(22865,1236,1357529177),(22866,1045,1355185735),(22872,1085,1355241472),(22891,1236,1357117086),(22892,1045,1358134075),(22917,1045,1357945476),(22917,1046,1357340462),(22936,1045,1357352933),(22957,1085,1355382819),(22973,1045,1357964128),(22994,1085,1355284097),(23015,1045,1356207957),(23084,1045,1357987552),(23084,1085,1355210977),(23104,1046,1357254221),(23107,1045,1357376382),(23123,1045,1357246582),(23200,1046,1357337931),(23211,1045,1357497375),(23245,1045,1357354758),(23302,1085,1355276709),(23348,1045,1355176779),(23358,1045,1357307555),(23374,1085,1355351919),(23385,1236,1357457021),(23428,1046,1357340801),(23580,1045,1357324218),(23684,1045,1357083092),(23705,1045,1357946443),(23737,1046,1357340017),(23764,1045,1357974964),(23841,1045,1357335232),(23841,1227,1357335230),(23841,1236,1357335211),(23864,1046,1356909262),(23865,1085,1355262684),(23873,1045,1357075672),(23891,1085,1355238460),(23997,1045,1355414494),(24010,1085,1355446779),(24059,1045,1357671293),(24075,1236,1355253502),(24140,1046,1355883325),(24221,1045,1357445028),(24222,1046,1357758287),(24287,1085,1355424730),(24314,1045,1357347921),(24372,1046,1357340511),(24373,1046,1357336421),(24427,1045,1357670949),(24427,1236,1357169911),(24444,1045,1355854067),(24453,1045,1357450056),(24454,1045,1358026218),(24518,1045,1355509154),(24587,1045,1358048547),(24620,1045,1357089792),(24620,1236,1355809429),(24643,1045,1357622265),(24720,1045,1355194836),(24723,1045,1355571592),(25390,1045,1357931647),(25523,1045,1357603474),(25648,1045,1357939590),(25648,1227,1357939588),(25692,1046,1357324159),(25753,1085,1355260944),(25828,1045,1357325835),(25878,1045,1357939900),(25988,1045,1357372740),(26002,1045,1357934611),(26072,1045,1357327728),(26194,1045,1355836139),(26206,1085,1355345625),(26223,1045,1357849265),(26239,1045,1358022933),(26239,1046,1356411870),(26243,1085,1355264572),(26567,1046,1357336141),(26607,1045,1357933805),(26607,1085,1355241178),(26621,1046,1357338723),(26725,1042,1358120818),(26725,1045,1358120819),(26725,1085,1355237672),(26769,1046,1356625733),(26772,1046,1357333276),(26815,1236,1357333099),(26887,1045,1357331803),(26887,1085,1355413065),(26946,1046,1355464518),(27016,1045,1357258424),(27069,1045,1357080459),(27154,1045,1357701261),(27206,1045,1357938773),(27206,1046,1357906367),(27206,1085,1355247261),(27226,1046,1357339290),(27231,1085,1355448429),(27314,1046,1357337861),(27339,1085,1355238500),(27374,1045,1357675206),(27374,1046,1357336350),(27459,1046,1355734950),(27481,1085,1355247262),(27495,1045,1357955778),(27499,1085,1355273249),(27524,1045,1357075272),(27549,1085,1355238539),(27569,1046,1357339466),(27580,1045,1357597150),(27594,1045,1357347017),(27604,1046,1357244511),(27739,1045,1357074114),(27830,1046,1357819451),(27871,1045,1356651103),(27953,1085,1355237089),(27996,1045,1357731670),(28026,15056,1355199565),(28063,1045,1357404867),(28095,1085,1355240282),(28153,1046,1357249329),(28225,1045,1357965209),(28323,1046,1356781611),(28361,1236,1355865932),(28527,1085,1355238224),(28546,1085,1355235489),(28549,1045,1357335589),(28557,1045,1357867090),(28587,1045,1355763348),(28656,1045,1357347176),(28671,1045,1355850830),(28671,1227,1355850829),(28701,1045,1357573718),(28716,1085,1355419655),(28839,1045,1358018384),(28878,1046,1357339233),(28925,1045,1357948103),(28950,1045,1357352422),(29042,1045,1355957410),(29052,1045,1357334276),(29095,1045,1357321469),(29142,1045,1357930220),(29177,1045,1357950270),(29196,1046,1357337995),(29207,1045,1357957777),(29224,1085,1355255613),(29382,1046,1357254379),(29406,1045,1357010797),(29406,1227,1357010796),(29413,1045,1358011857),(29413,1227,1356100071),(29563,1046,1357337302),(29571,1046,1357338307),(29573,1046,1357276249),(29599,1045,1357246110),(29672,1045,1357327889),(29719,1045,1357970589),(29750,1045,1357331733),(29774,1045,1357345677),(29813,1236,1357074115),(29864,1236,1357173429),(29878,1045,1355784937),(29935,1045,1357142898),(29935,1085,1355279263),(30014,1085,1355245773),(30050,1045,1357115009),(30152,15068,1355376195),(30157,1045,1355537681),(30159,1045,1358093144),(30171,1046,1357336154),(30239,1085,1355294798),(30289,1085,1355244337),(30293,1046,1357340131),(30369,1045,1357335937),(30369,1227,1357275420),(30369,1236,1357275393),(30409,1085,1355240040),(30414,1045,1357951279),(30433,1046,1357153297),(30437,1085,1355257546),(30446,1085,1355240249),(30468,1045,1355177870),(30477,1046,1357337595),(30527,1046,1357938078),(30536,1085,1355259611),(30538,1045,1357348126),(30605,1046,1356481205),(30854,1045,1357077378),(30863,1085,1355439761),(30966,1236,1355857310),(31011,1045,1357616804),(31041,1085,1355289611),(31066,1045,1355567638),(31084,1045,1358137071),(31084,1046,1357325020),(31095,1045,1356631200),(31104,1045,1357946434),(31110,1236,1355241652),(31161,1045,1357681632),(31161,1046,1357682069),(31161,1227,1357681628),(31161,1236,1357681732),(31168,1045,1355890319),(31168,1046,1357335997),(31189,1236,1358053500),(31189,15044,1355176876),(31203,1045,1357358765),(31223,1046,1357341244),(31231,1045,1357245403),(31240,1085,1355255706),(31270,1046,1357337055),(31378,1045,1357334131),(31396,1085,1355245926),(31460,1046,1357335099),(31480,1045,1357075673),(31562,1085,1355237484),(31575,1085,1355242036),(31716,1045,1357687447),(31879,1045,1357255245),(31956,1046,1357326820),(31997,1045,1356105318),(31997,1227,1356105311),(32114,1045,1358086695),(32114,1046,1357339276),(32114,1227,1356840625),(32114,1236,1357690803),(32143,1045,1357947791),(32144,1085,1355253021),(32164,1045,1357268286),(32229,1045,1355867135),(32294,1045,1357754428),(32335,1045,1357364274),(32368,1046,1357338490),(32368,1085,1355244752),(32422,1045,1357946611),(32481,1085,1355238854),(32518,1045,1357338078),(32518,1046,1357338398),(32518,1227,1357338075),(32547,1085,1355254344),(32591,1045,1355608581),(32680,1236,1357325030),(32763,1046,1357337311),(33192,1045,1357937300),(33198,1045,1356939339),(33198,1227,1356939337),(33198,1236,1356939423),(33238,1045,1357359077),(33253,1045,1357952985),(33284,1045,1357586709),(33284,1046,1356809361),(33310,1045,1357958220),(33419,1045,1356018979),(33419,1227,1356018978),(33445,1045,1357693593),(33496,1236,1355273882),(33592,1085,1355274287),(33616,1045,1357259381),(33616,1227,1357259277),(33673,1045,1357943410),(33676,1045,1357654079),(33687,1045,1357922008),(33724,1045,1357353927),(33846,1045,1357358358),(33886,1236,1356016021),(34209,1045,1357251224),(34504,1045,1357994842),(34516,1046,1357336624),(34534,1045,1358020602),(34584,1085,1355241425),(34609,1046,1355397261),(34666,1045,1357953820),(34681,1045,1357358297),(34681,1046,1357358270),(34687,1046,1357341482),(34768,1046,1357338516),(34780,1045,1357329360),(34780,1085,1355239605),(34800,1045,1357077320),(34834,1045,1357082956),(34844,1045,1357936614),(34844,1046,1357326871),(34870,1045,1357677627),(34870,1046,1356316468),(34938,1085,1355197900),(34939,1046,1357336444),(34961,1045,1357110276),(34980,1045,1357353285),(35020,1046,1357336909),(35106,1045,1357938131),(35106,1085,1355242093),(35137,1045,1357957412),(35137,1046,1356236614),(35166,1045,1357365816),(35325,1045,1355194670),(35355,1045,1356413930),(35429,1045,1355766476),(35429,1227,1355766474),(35429,15070,1355448868),(35499,1045,1356800112),(35561,1046,1357339876),(35595,1045,1357663188),(35595,1046,1357336850),(35681,1045,1356835255),(35890,1045,1358108579),(35890,1046,1358109527),(35958,1045,1357348664),(35966,1045,1357945198),(35996,1085,1355245227),(36014,1085,1355248690),(36029,1045,1357231843),(36029,1046,1357336056),(36049,1045,1355871593),(36085,1039,1357676282),(36085,1046,1357676284),(36092,1045,1355843337),(36119,1046,1357337359),(36201,1046,1357337764),(36226,1046,1357337941),(36231,1085,1355237388),(36244,1045,1357592616),(36244,1046,1357337687),(36251,1045,1357373700),(36251,1046,1357339425),(36251,1085,1355285290),(36342,1236,1357084756),(36426,1085,1355245241),(36436,1045,1357259280),(36477,1085,1355248653),(36524,1045,1357933376),(36524,1085,1355241144),(36608,1046,1357338996),(36624,1085,1355243079),(36655,1045,1357933074),(36766,1045,1357347844),(36824,1045,1357944015),(36897,1085,1355245538),(36972,1045,1356106797),(36972,1227,1356106797),(37063,1045,1358006235),(37097,1045,1357348525),(37186,1085,1355419645),(37364,1045,1357496267),(37364,1085,1355239657),(37388,1042,1358084490),(37388,1045,1358084493),(37734,1045,1357359155),(37778,1045,1355242471),(37778,1085,1355242454),(37781,1045,1357671229),(37941,1045,1357624305),(37941,1046,1357624312),(38030,1045,1355812936),(38196,1045,1357334088),(38196,1227,1357334087),(38337,1046,1357336174),(38363,1045,1357967942),(38412,1085,1355283616),(38435,1045,1355845424),(38514,1042,1357336529),(38514,1046,1357336530),(38514,15091,1357244868),(38524,1045,1358097927),(38583,1045,1358001644),(38583,1046,1357337245),(38608,1045,1357949477),(38617,1236,1357527667),(38632,1085,1355188870),(38693,1045,1357677294),(38797,1045,1355836803),(38801,1045,1357352832),(38831,1045,1357943896),(38836,1045,1357359339),(38836,1227,1357359251),(38836,1236,1358003064),(38900,1085,1355250451),(38910,1045,1357933030),(38910,1085,1355344941),(38988,1085,1355246620),(38998,1045,1356124028),(38998,1085,1355250308),(39004,1045,1357080201),(39005,1046,1357337690),(39016,1045,1357327942),(39048,1045,1357366131),(39088,1045,1357967532),(39170,1045,1356971371),(39189,1045,1357673194),(39363,1046,1357340305),(39441,1045,1357352768),(39525,1045,1356971831),(39565,1045,1356136935),(39632,1045,1357502896),(39727,1045,1357583107),(39794,1045,1357684690),(39870,1085,1355237861),(40065,1085,1355239459),(40208,1045,1357941954),(40213,1045,1357598026),(40373,1045,1357618310),(40564,1045,1357087661),(40636,1045,1357933454),(40720,1045,1357933850),(40805,1085,1355235400),(40817,1045,1357335875),(40817,1046,1357335941),(40860,1045,1357249327),(40860,1046,1357249331),(40877,1085,1355275171),(40909,1045,1356126436),(40966,1046,1357337576),(41010,1045,1357335726),(41062,1045,1355186265),(41079,1045,1357622421),(41080,1045,1357322023),(41332,1045,1355508491),(41332,1046,1356105878),(41332,1236,1356299173),(41640,1045,1357401215),(41683,1045,1357935792),(41719,1045,1355819258),(41719,1227,1355819257),(41734,1085,1355262988),(41840,1085,1355301401),(41895,1045,1356138237),(41914,1085,1355239461),(41942,1045,1356123534),(41946,1046,1356458178),(42671,1045,1355839910),(42676,1045,1357662671),(42734,1045,1357841561),(42735,1045,1357939544),(42751,1085,1355241148),(42760,1045,1358019939),(42770,1045,1356657097),(42834,1045,1355192096),(42849,1046,1357335155),(42894,1045,1357746483),(42911,1045,1357489034),(42974,1045,1357352418),(42978,1046,1357337974),(43033,1045,1357335555),(43059,1046,1357346400),(43075,1045,1358083088),(43075,1046,1358083194),(43087,1085,1355235963),(43141,1046,1357083621),(43144,1045,1357358643),(43153,1046,1357249339),(43169,1045,1357081566),(43220,1045,1357926042),(43241,1045,1357347668),(43359,1045,1357353294),(43371,1045,1357246273),(43371,1046,1357339022),(43491,1045,1357953580),(43501,1045,1357328009),(43522,1045,1357359777),(43614,1045,1355886270),(43622,1045,1357737545),(43622,1046,1356383678),(43622,1227,1356683896),(43634,1045,1357935031),(43635,1045,1356532975),(43635,1085,1355489132),(43743,1085,1355236942),(43748,1045,1358091064),(43758,1085,1355243121),(43778,1045,1358017720),(43778,1046,1358017877),(43957,1045,1357680143),(43964,15094,1357075562),(44155,1046,1357340477),(44157,1045,1357077268),(44212,1045,1355808801),(44246,1236,1357157221),(44247,1045,1357345687),(44320,1045,1357086391),(44469,1236,1355813767),(44731,1045,1358009534),(44818,1045,1356473097),(44858,1085,1355240931),(44859,1045,1357588065),(44927,1045,1357968556),(44927,1227,1357968555),(44945,1045,1357587298),(45019,1085,1355244697),(45036,1085,1355248867),(45047,1046,1357326888),(45137,1045,1357248646),(45144,1040,1357346278),(45144,1045,1357346279),(45144,1046,1357337624),(45163,1045,1357933178),(45325,1085,1355239034),(45335,1045,1357938511),(45381,1045,1357852033),(45386,1045,1358026579),(45386,1046,1357336364),(45401,1045,1357348588),(45447,1045,1357359149),(45471,1046,1357323666),(45471,1085,1355241670),(45500,1045,1357527172),(45547,1045,1357961226),(45660,1045,1357226076),(45800,1045,1355507180),(45825,1046,1357336864),(45838,1085,1355262650),(45843,1085,1355361850),(45906,1045,1357334079),(46007,1085,1355243650),(46055,1045,1355531541),(46073,1045,1355836868),(46095,1045,1358012599),(46117,1045,1355429430),(46117,1236,1357386560),(46118,1045,1357953258),(46277,1045,1357986985),(46359,1045,1357754514),(46429,1045,1357328040),(46516,1236,1355868516),(46553,1045,1355619506),(46553,1085,1355250443),(46576,1045,1355513287),(46591,1045,1358051899),(46595,1045,1357938635),(46603,1045,1356125827),(46632,1046,1357336755),(46819,1045,1357607094),(46848,1045,1357335436),(46898,1045,1357373381),(46941,1045,1357764940),(46941,1236,1357076049),(46961,1045,1357940309),(46961,1046,1357727421),(47008,1085,1355250731),(47017,1046,1357336217),(47017,1085,1355236692),(47134,1046,1357326907),(47154,1085,1355240806),(47211,1085,1355329449),(47283,1045,1357854291),(47283,15094,1357856054),(47288,1045,1358001258),(47404,1045,1357316821),(47427,1045,1357263972),(47537,1045,1358011050),(47552,1046,1357338430),(47602,1045,1357341150),(47602,1046,1357341151),(47602,1085,1355183357),(47644,1046,1357337259),(47649,1045,1357341231),(47649,1046,1357341409),(47665,1045,1356991406),(47665,1236,1357062409),(47734,1046,1356754160),(47753,1045,1357318656),(47753,1227,1357318655),(47753,1236,1357322869),(47774,1085,1355247066),(47809,1085,1355253779),(47883,1045,1358139963),(47900,1045,1356531066),(47900,1227,1356531065),(47900,1236,1356531050),(47932,1045,1357346536),(47980,1046,1357337004),(48069,1046,1357270726),(48082,1045,1357491265),(48115,1085,1355236638),(48136,1045,1357358158),(48147,1085,1355236823),(48214,1045,1358131023),(48240,1045,1357931862),(48253,1045,1355609714),(48253,1046,1355465022),(48384,1085,1355270929),(48438,1045,1357344949),(48438,1227,1357344949),(48438,1236,1357344917),(48444,1046,1357909707),(48616,1045,1357276997),(48681,1045,1355350109),(48690,1045,1355970734),(48726,1045,1357628432),(48735,1045,1357944323),(48840,1085,1355246803),(48881,1236,1355950269),(48901,1085,1355237649),(48973,1045,1357143813),(48996,1045,1358041333),(49023,1042,1357337308),(49023,1046,1357337708),(49023,1236,1357401827),(49051,1085,1355244652),(49238,1085,1355235661),(49430,1085,1355242180),(49451,1046,1355883336),(49457,1045,1357705422),(49482,1046,1357343597),(49515,1046,1356631358),(49544,1045,1355516522),(49544,1046,1357338241),(49662,1045,1357940928),(49662,1046,1357337578),(49670,1045,1357256191),(49867,1046,1355423460),(49870,1045,1357942718),(49877,1045,1357228961),(49940,1046,1357325157),(50063,1045,1357316576),(50070,1045,1355810728),(50188,1045,1355182734),(50200,1046,1357339616),(50232,1045,1357328028),(50243,1046,1357336758),(50263,1085,1355245033),(50274,1045,1357245420),(50322,1045,1355524296),(50342,1046,1357337494),(50375,1045,1357327847),(50412,1046,1357138946),(50423,1045,1357608550),(50492,1046,1357336739),(50562,1085,1355277315),(50662,1045,1357060006),(50704,1046,1355176328),(50715,1045,1358008786),(50725,1045,1358007623),(50749,1045,1357618418),(50749,1046,1357705203),(50752,1045,1357328055),(50799,1045,1355292424),(50799,1227,1355292421),(50839,1045,1357901442),(50865,1045,1355921986),(50910,1045,1357341498),(50936,1045,1357698957),(50980,1045,1357582515),(50993,1045,1358127122),(50994,1045,1357329135),(51027,1045,1357945964),(51038,1045,1357964592),(51044,1085,1355241525),(51045,1045,1357410757),(51045,1227,1357410755),(51045,1236,1357410743),(51087,1085,1355243589),(51111,1045,1358017006),(51111,1085,1355248342),(51128,1045,1357255151),(51132,1085,1355243524),(51149,1085,1355235812),(51159,1045,1357354152),(51170,1045,1357936755),(51197,1085,1355264472),(51214,1045,1357347842),(51296,1045,1358153073),(51296,1046,1356338269),(51460,1236,1355809578),(51567,1045,1355400706),(51612,1046,1357336362),(51641,1085,1355487414),(51680,1045,1357352150),(51793,1046,1357339765),(51913,1046,1356624860),(51942,1045,1355322451),(52049,1045,1356307040),(52101,1085,1355257988),(52116,1045,1358002975),(52116,1236,1357350646),(52152,1045,1357945130),(52220,1045,1356277827),(52224,1045,1357359626),(52232,1045,1355749214),(52274,1085,1355254033),(52444,1045,1357618541),(52479,1045,1357335534),(52512,1045,1357372012),(52520,1045,1357366510),(52544,1045,1357245516),(52624,1045,1357444121),(52624,1085,1355242336),(52624,1227,1357444121),(52685,1236,1355512528),(52729,1045,1356121874),(52753,1045,1355811559),(52806,1046,1357339539),(52829,1085,1355239331),(52865,1045,1356146709),(52865,1227,1356146708),(53130,1236,1355830972),(53142,1236,1357237507),(53259,1085,1355256727),(53297,1045,1357347023),(53297,1085,1355268612),(53310,1045,1357837786),(53310,1236,1357837751),(53321,1045,1358136888),(53506,1045,1356182735),(53511,1046,1357336951),(53512,1046,1357337449),(53555,1045,1358015131),(53752,1085,1355285880),(53919,1045,1357333295),(53919,1227,1357333294),(53919,1236,1357333429),(53933,1085,1355247112),(53999,1045,1355844194),(54055,1085,1355413726),(54149,1045,1357310899),(54195,1085,1355242363),(54294,1045,1357233997),(54314,1085,1355267734),(54448,1045,1357345667),(54507,1085,1355496221),(54515,1085,1355284983),(54560,1045,1357941667),(54571,1085,1355239848),(54596,1046,1357337455),(54686,1045,1357491941),(54686,1227,1357491939),(54713,1045,1357309072),(54714,1045,1357959057),(54933,1236,1357332350),(54998,1045,1358018273),(55018,1046,1357254250),(55050,1046,1357576482),(55069,1045,1357937142),(55069,1085,1355314884),(55212,1045,1355512469),(55287,1085,1355925158),(55316,1045,1357952270),(55435,1045,1357358547),(55623,1236,1357591139),(55633,1046,1357253669),(55786,1045,1357327971),(55832,1045,1356832200),(55850,1045,1358008763),(55858,1045,1357937965),(55858,1085,1355257202),(55913,1045,1357933280),(55963,1085,1355253383),(55977,1045,1357363495),(56023,1085,1355278066),(56123,1046,1357338379),(56174,1045,1355972281),(56174,1085,1355239729),(56176,1045,1357106587),(56184,1045,1356152934),(56184,1046,1357340394),(56247,1045,1357593558),(56362,1045,1357684091),(56436,1085,1355236238),(56489,1046,1357336648),(56530,1045,1357846657),(56594,1045,1355258078),(56594,1227,1355258078),(56644,1085,1355240326),(56645,1045,1357331078),(56645,1227,1357331077),(56647,1045,1358005506),(56705,1046,1357341427),(56722,1085,1355356093),(56726,1046,1357339870),(56803,1045,1357319211),(56803,1236,1357319280),(56872,1045,1357934088),(56896,1045,1357352662),(56896,1085,1355369661),(56908,1045,1357932606),(56999,1045,1358136022),(56999,1046,1358136011),(57016,1045,1357436567),(57023,1045,1357951289),(57032,1045,1357276614),(57032,1227,1357276613),(57094,1046,1358122219),(57101,1085,1355349603),(57139,1045,1357949547),(57170,1045,1357666498),(57170,1046,1357323614),(57191,1045,1357934079),(57288,1045,1357466380),(57288,1046,1357816774),(57325,1045,1357967685),(57329,1045,1358096217),(57338,1046,1357340353),(57344,1085,1355249155),(57370,1085,1355239575),(57407,1045,1357359940),(57415,1045,1357939342),(57437,1045,1357957326),(57507,1236,1357489190),(57571,1046,1357324754),(57575,1085,1355186127),(57600,1046,1357338195),(57631,1085,1355300482),(57634,1045,1357948857),(57644,1046,1357336985),(57652,1236,1357367776),(57736,1045,1357563123),(57747,1236,1357140650),(57789,12845,1355995010),(57870,1045,1357945085),(57965,1045,1357249901),(58000,1045,1357696257),(58001,1045,1355861291),(58035,1085,1355244795),(58052,1085,1355245306),(58078,1045,1355523485),(58078,1085,1355242566),(58175,1085,1355236910),(58205,1085,1355272525),(58289,1045,1357075921),(58345,1045,1355523490),(58356,1085,1355179451),(58406,1045,1357755613),(58429,1236,1357163350),(58480,1045,1355812053),(58485,1045,1357250898),(58530,1045,1357947978),(58643,1045,1357329129),(58643,1046,1357340018),(58726,1042,1357337620),(58726,1046,1357337621),(58766,1045,1357327878),(58819,1085,1355246755),(59046,1045,1357330232),(59150,1045,1358129434),(59208,1045,1357327963),(59403,1045,1356123056),(59440,1085,1355236067),(59498,1045,1357323220),(59498,1046,1357323621),(59573,1045,1357663106),(59607,1046,1357338799),(59607,1085,1355236646),(59660,1045,1357972649),(59663,1236,1357401633),(59695,1045,1355807508),(59695,1085,1355358492),(59700,1085,1355239872),(59789,1045,1358005805),(59823,1045,1357374194),(59830,1085,1355235638),(59864,1085,1355238065),(59898,1046,1357560951),(59914,1045,1355519241),(59947,1046,1357338868),(59959,1045,1356037428),(60015,1046,1357340472),(60021,1236,1356095835),(60098,1045,1357328031),(60177,1085,1355238621),(60260,1045,1355860340),(60299,1046,1357336463),(60317,1236,1357331071),(60343,1045,1357348554),(60360,1046,1357327153),(60363,1045,1356157557),(60454,1045,1357347352),(60465,1045,1356131069),(60502,1045,1357949117),(60502,1046,1357337333),(60505,1085,1355274878),(60587,1236,1355540598),(60594,1045,1355872326),(60594,1085,1355260920),(60595,1045,1357963682),(60606,1085,1355345690),(60613,1045,1357371059),(60619,1045,1358003997),(60619,1046,1357336862),(60648,1046,1356998117),(60820,1040,1355848169),(60820,1045,1355848145),(60946,1045,1357608969),(60946,15107,1357950147),(60966,1085,1355250832),(61163,1046,1357650046),(61305,15070,1355506991),(61387,1045,1356173190),(61387,1046,1357340444),(61442,1085,1355340588),(61520,1045,1357172605),(61714,1045,1355193522),(61776,1045,1357632012),(61781,1045,1357850209),(61809,1046,1355338618),(61888,1045,1357249334),(61936,1045,1357359306),(61950,1236,1355202082),(61981,1045,1357349893),(62074,1045,1356572619),(62107,1085,1355263773),(62114,1085,1355185402),(62165,1045,1357131027),(62178,1046,1355843656),(62178,1236,1355843558),(62215,1045,1356973595),(62227,1045,1355808167),(62267,1046,1357337988),(62285,1045,1357342617),(62285,1046,1357339734),(62289,1046,1357338227),(62300,1045,1355189734),(62341,1046,1357254578),(62359,1045,1357973968),(62359,1236,1357168792),(62445,1045,1356142594),(62446,1045,1357938133),(62521,1045,1357255891),(62560,1045,1358071004),(62574,15051,1355278752),(62642,1085,1355283991),(62829,1236,1357670378),(62964,1085,1355239895),(63079,1045,1357359931),(63151,1045,1358004465),(63211,1236,1357325219),(63328,1236,1357324465),(63337,1045,1355863448),(63383,1045,1357353456),(63440,1236,1357335759),(63441,1085,1355243518),(63502,1045,1357352545),(63532,1045,1357476187),(63534,1045,1357353150),(63708,1085,1355243617),(63766,1045,1357934063),(63773,1045,1355431110),(63773,1085,1355238676),(63782,1085,1355319130),(63796,1045,1357673409),(63815,1046,1357338180),(63833,1045,1357076545),(63838,1085,1355279663),(63857,1085,1355250983),(63996,1085,1355240747),(64006,1046,1357768077),(64036,1045,1355835065),(64107,1085,1355268288),(64156,1045,1357940029),(64248,1045,1357327883),(64253,1045,1355511873),(64259,1045,1357358387),(64259,1085,1355451899),(64304,1045,1357077362),(64440,1046,1357337358),(64529,1045,1357245455),(64610,1236,1357327683),(64623,1045,1357098263),(64659,1046,1357817485),(64779,1045,1358026410),(64780,1045,1357859691),(64799,1045,1357618185),(64805,1085,1355458718),(64843,1046,1357337492),(64858,1085,1355368497),(64893,1046,1357337591),(64895,1046,1357337394),(64916,1045,1358095619),(64926,1046,1357336751),(64968,1046,1357336244),(64978,1045,1357932301),(65021,1045,1357245516),(65046,1045,1357263268),(65160,1045,1357434583),(65160,1227,1357434581),(65171,1040,1356795453),(65171,1045,1356795453),(65220,1045,1358038688),(65366,1045,1357358826),(65375,1085,1355246296),(65406,1085,1355241049),(65579,1045,1355259736),(65579,1085,1355259721),(65588,1046,1355855218),(65588,1085,1355252155),(65603,1046,1357337411),(65652,1045,1355890128),(65929,1045,1357334198),(65930,1046,1357528401),(66126,1085,1355238758),(66237,1045,1358126386),(66498,1085,1355238472),(66646,1045,1357337443),(66646,1046,1357337477),(66667,1045,1357084314),(66856,1045,1355247280),(66856,1085,1355247265),(67051,1045,1356133126),(67122,1045,1355599362),(67143,1085,1355244980),(67170,1046,1356107945),(67170,1085,1355239843),(67215,1046,1357338695),(67253,1045,1357936622),(67261,1045,1357674061),(67268,1045,1356103073),(67268,1085,1355244858),(67268,3049,1356103033),(67268,11556,1356103022),(67328,1045,1357762784),(67387,1085,1355240163),(67419,1236,1357330192),(67480,1085,1355249991),(67493,1046,1357339638),(67524,1085,1355276717),(67762,1046,1357680328),(67821,1045,1357327965),(67841,1045,1357259396),(67862,1045,1356155344),(67862,1085,1355178948),(67907,1046,1357254340),(67907,1236,1357328855),(67949,1085,1355243208),(67958,1045,1355814089),(68059,1045,1357337644),(68138,1042,1357340604),(68138,1046,1357340624),(68142,1085,1355250517),(68255,1045,1357365222),(68310,1045,1355841349),(68322,1045,1355515656),(68334,1046,1357333266),(68426,1045,1356131845),(68432,1085,1355256691),(68477,1045,1355809810),(68516,1045,1357340927),(68516,1046,1357340926),(68516,1236,1357662522),(68747,1045,1357365922),(68798,1046,1355176170),(68879,1046,1357340664),(68968,1045,1355835959),(69231,1045,1357660322),(69322,1085,1355240215),(69327,1045,1357983819),(69454,1045,1357353974),(69467,1046,1357338304),(69480,1045,1358004937),(69597,1045,1355820924),(69695,1085,1355367476),(69897,1045,1357933286),(70052,1045,1357076346),(70082,1045,1357944192),(70082,1236,1357944187),(70213,1045,1357353729),(70217,1045,1357767136),(70307,1045,1355876759),(70347,1045,1358039806),(70428,1046,1357336202),(70444,1046,1357243751),(70475,1045,1358018926),(70613,1045,1356196279),(70624,1045,1357934985),(70723,1045,1356800760),(70876,1045,1355634578),(70896,1045,1357269894),(70972,1046,1357326883),(71080,1045,1357952586),(71227,1045,1355835392),(71284,1045,1357774512),(71298,1045,1355188076),(71368,1045,1357936417),(71466,1045,1357112866),(71468,1045,1355183630),(71506,1045,1357961553),(71506,1046,1357637788),(71517,1236,1357074507),(71600,1045,1357264130),(71662,1046,1357336100),(71714,1045,1355238460),(71773,1045,1357309318),(71773,1046,1357041526),(71895,15105,1357935676),(71923,1045,1356062510),(72092,1085,1355237194),(72149,2881,1357674788),(72233,1045,1357612273),(72233,1236,1357332291),(72488,1085,1355253177),(72520,1045,1357367068),(72549,1046,1357341338),(72570,1236,1356740989),(72601,1085,1355252341),(72641,1045,1355179161),(72649,1045,1356123298),(72677,1045,1358093131),(72677,1046,1357662063),(72686,1046,1357336965),(72733,1045,1358082665),(72758,1045,1357686766),(72781,1045,1357933160),(72795,1046,1357337478),(72871,1045,1357252285),(73035,1045,1357249416),(73110,1046,1357337827),(73166,1045,1356657571),(73172,1045,1356120413),(73172,1085,1355251130),(73181,1046,1357336918),(73208,1085,1355269029),(73248,1046,1357254265),(73296,1045,1357942861),(73354,1085,1355246794),(73367,1045,1358016669),(73433,1045,1357245297),(73681,1236,1355838334),(73694,1045,1356119079),(73694,1085,1355262499),(73737,1045,1355761298),(73827,1045,1355962513),(73952,1085,1355264122),(74024,1045,1357917544),(74076,1085,1355247571),(74093,1045,1355528693),(74093,1085,1355443116),(74232,15039,1355968304),(74232,15078,1355955902),(74237,1045,1356140308),(74237,1085,1355255746),(74241,1045,1355859238),(74351,1045,1356974446),(74370,1085,1355278603),(74371,1046,1358060521),(74384,1045,1358087879),(74409,1045,1357962084),(74422,1046,1355883663),(74431,1045,1357365061),(74519,1046,1357553991),(74519,1236,1356263629),(74535,1085,1355304169),(74650,1046,1357336791),(74699,1045,1357662678),(74736,1045,1355514656),(74820,1045,1357328017),(74828,1046,1355728456),(74896,1045,1357815100),(74961,1045,1357932503),(75064,1045,1356972084),(75150,1045,1356123788),(75212,1045,1355721016),(75215,1045,1357852459),(75224,1236,1357327405),(75290,1045,1356207021),(75290,1085,1355246779),(75339,1045,1358136364),(75339,1046,1358135899),(75368,1045,1357077669),(75369,1045,1357959667),(75620,1085,1355243648),(75632,1085,1355263686),(75667,1085,1355458451),(75785,1046,1355559771),(75874,1045,1357942790),(75949,1085,1355371011),(75967,1045,1357943376),(76071,1045,1355240735),(76071,1085,1355239598),(76084,1045,1357351205),(76084,1236,1355509061),(76098,1085,1355240439),(76104,1085,1355253746),(76126,1045,1355789830),(76127,1045,1357961478),(76257,1042,1357337849),(76257,1046,1357337850),(76264,1085,1355265995),(76473,1045,1357247723),(76538,1045,1357077718),(76673,1085,1355243071),(76852,1045,1357413458),(76882,1045,1357941183),(77160,1085,1355246134),(77215,1045,1357948118),(77428,1045,1358099074),(77428,1046,1357336208),(77453,1045,1358089684),(77652,1040,1357980561),(77652,1042,1357980421),(77652,1045,1357982228),(77656,1045,1355887357),(77752,1045,1358113240),(77791,1045,1357856994),(77842,1045,1357359339),(77864,1045,1357247349),(77877,1045,1357958263),(77880,1046,1355656913),(77927,1085,1355274224),(77946,1045,1357088522),(77988,1045,1357324260),(78019,1045,1357948238),(78027,1045,1357421749),(78027,1085,1355253903),(78027,1227,1357421748),(78027,1236,1357421769),(78097,1085,1355238801),(78120,1045,1357329493),(78120,1227,1357329492),(78120,1236,1357330231),(78135,1085,1355235435),(78166,1085,1355197543),(78206,1046,1357336316),(78375,1045,1358090888),(78384,1046,1357340160),(78418,1046,1357336273),(78461,1045,1357938334),(78501,1085,1355237258),(78503,1045,1357792266),(78530,1045,1357123576),(78651,1045,1357936610),(78651,1085,1355235976),(78662,1236,1355231659),(78699,1046,1357341431),(78791,1045,1356139219),(78935,1046,1357880551),(79000,1045,1357247854),(79005,1085,1355285403),(79063,1045,1355193631),(79088,1085,1355274451),(79097,1045,1355837937),(79260,1045,1357951002),(79311,1045,1357953202),(79342,1085,1355256356),(79351,1045,1357703969),(79457,1045,1357954718),(79466,1045,1357327881),(79816,1085,1355268641),(79867,1085,1355237671),(79976,1045,1357249105),(79988,1045,1357327977),(80145,1085,1355236932),(80361,1045,1357679033),(80379,1046,1357332114),(80452,1046,1357339185),(80621,1045,1355807117),(80718,1045,1357077350),(80732,1046,1357324160),(80972,1085,1355237771),(81229,1045,1357963519),(81658,14027,1357075341),(81674,1045,1357251225),(81924,1045,1357363946),(81928,1045,1357945375),(82143,1045,1355857072),(82184,1045,1357248019),(82238,1045,1357346934),(82283,1085,1355252633),(82328,1046,1357339130),(82871,1045,1358116469),(83243,1045,1355185492),(83243,1227,1355185491),(83360,1046,1355176339),(83498,1045,1357949508),(83502,1045,1355870329),(83546,1045,1357612123),(83573,1046,1355384411),(83722,1045,1357371171),(83722,1046,1355298354),(83722,1085,1355298095),(83799,1085,1355236636),(83836,1046,1357604046),(83866,1045,1355203557),(84070,1046,1357515125),(84219,1042,1357337958),(84219,1046,1357337959),(84384,1046,1357324089),(84427,1045,1355535521),(84469,1045,1357947376),(84537,1045,1355807359),(84629,1045,1357074398),(84758,1046,1357254783),(85382,1085,1355419996),(85445,1046,1357759446),(85613,1045,1357954837),(85694,1045,1357943498),(86280,1046,1357326921),(86461,1045,1358124342),(86508,1045,1357859920),(86508,1046,1357338721),(86830,1045,1357226232),(87043,1045,1357370775),(87129,1045,1357933683),(87249,1046,1358109740),(87250,1046,1357338285),(87304,1045,1358093580),(87304,1085,1355238386),(87364,1045,1358029448),(87364,1046,1357340278),(87494,1045,1357933704),(87528,1046,1357758147),(87574,1045,1357541801),(87606,1045,1357768560),(87610,1045,1357584921),(87621,1045,1357358586),(87647,1045,1357323783),(87801,1045,1357614117),(88106,1046,1357341203),(88134,1046,1357339307),(88180,1045,1355933552),(88206,1045,1357942773),(89186,1045,1357747956),(89286,1045,1357249149),(89335,1046,1357341084),(89472,1085,1355244140),(89494,1085,1355251273),(89530,1045,1357682661),(89565,1046,1357336296),(89591,1085,1355244632),(89598,1046,1357338864),(89683,1085,1355235892),(89762,1085,1355238426),(89825,1236,1357323917),(89870,1045,1357335782),(89870,1046,1357336198),(89875,1045,1356210331),(89933,1045,1357341223),(89933,1046,1357341218),(90012,1045,1357934644),(90028,1046,1356300934),(90131,1045,1356135424),(90177,1046,1357604047),(90216,1045,1357782039),(90246,1046,1357341488),(90307,1045,1357244377),(90317,1046,1357339512),(90340,1045,1357229211),(90358,1045,1355807616),(90503,1045,1357366257),(90573,1045,1357933090),(90578,1085,1355189706),(90635,1046,1357275086),(90636,1085,1355241996),(90639,1236,1355844407),(90656,1045,1355177589),(90658,1045,1357082705),(90658,1046,1357339528),(90718,1045,1357976254),(90742,1085,1355292298),(90799,1085,1355239015),(90909,1045,1357748039),(90980,1045,1355866515),(91094,1045,1355190372),(91099,1045,1357327897),(91196,1085,1355280953),(91308,1045,1357833503),(91436,1045,1357327916),(91526,1085,1355266969),(91536,1236,1357684203),(91565,1045,1357327914),(91619,1045,1358119558),(91619,1046,1357338197),(91658,1045,1357244748),(91667,1085,1355267916),(91674,1045,1355820396),(91706,1045,1357334306),(91716,1045,1357335499),(91773,1236,1357326322),(91794,1046,1357340221),(91824,1045,1358015537),(91845,1046,1357336132),(91884,1045,1357077928),(91919,1045,1357908334),(91937,1085,1355281136),(91975,1085,1355236343),(92008,1046,1357324154),(92095,1045,1357947905),(92112,1085,1355241583),(92181,1045,1357340812),(92181,1046,1357340809),(92209,1045,1357397829),(92209,1227,1357397828),(92311,1045,1358096495),(92317,1085,1355238708),(92328,1045,1358048665),(92427,1045,1355175111),(92439,1046,1357338907),(92484,1042,1357341225),(92484,1046,1357341377),(92541,1085,1355208783),(92657,1045,1355882466),(92657,1227,1355882465),(92697,1045,1357386617),(92735,1045,1355849539),(92760,1045,1356727432),(93067,1045,1357537707),(93300,1045,1357598854),(93529,1085,1355237312),(93625,1085,1355241929),(93627,1045,1355973381),(93707,1045,1357076013),(93755,1046,1357326759),(93797,1045,1357075292),(93878,1045,1357264165),(93934,1085,1355276405),(94018,1085,1355253550),(94137,1045,1357245075),(94145,1045,1358088378),(94159,1045,1357851502),(94159,15087,1357842645),(94159,15091,1357850804),(94161,1085,1355195891),(94222,1045,1355201882),(94229,1085,1355273003),(94281,1045,1357607219),(94321,1045,1357966859),(94359,1045,1357254918),(94414,1045,1356120348),(94429,1045,1357791096),(94500,1045,1357984696),(94500,1046,1357984601),(94572,1045,1357253566),(94626,1046,1357023885),(94804,1045,1357359669),(95085,1045,1357709563),(95085,1085,1355279942),(95772,1045,1358123722),(96272,15095,1356729725),(96394,1045,1357437451),(96519,1045,1357946706),(96679,1046,1357339943),(96722,1045,1357976597),(96744,1085,1355258714),(96748,1045,1355846328),(96790,1085,1355242823),(97093,1085,1355348043),(97175,1045,1357334125),(97255,1045,1357349700),(97431,1045,1357938295),(97860,1045,1357080786),(98312,1046,1357338968),(98367,1045,1357704017),(98441,1045,1357131756),(98649,1045,1357327869),(98670,1045,1357640999),(98670,1046,1357641061),(98984,1045,1357312336),(99284,1045,1357502091),(99456,1045,1357664593),(99895,1085,1355177522),(99907,1045,1357248548),(99921,1046,1357338325),(100006,1045,1357663646),(100073,15097,1357349697),(100643,1046,1357326987),(100644,1045,1357327698),(100899,1045,1355513679),(100929,1085,1355244099),(100950,1046,1357337986),(101179,1046,1357326925),(101205,1045,1357358738),(101249,851,1356036782),(101697,1045,1357938265),(101799,1045,1357089975),(101929,1045,1357944502),(102066,1046,1357324104),(103560,1046,1357326899),(103676,1045,1357365278),(103676,1236,1357235680),(103731,1045,1357945898),(103731,1046,1357337027),(103780,1045,1357261449),(103827,1045,1357075698),(103871,1045,1357080410),(103976,1045,1357327251),(104060,1045,1356126474),(104262,1045,1355509556),(104262,1085,1355259173),(104286,1045,1355366866),(104286,1227,1355366866),(104437,1045,1357400834),(104437,1227,1357400833),(104440,1045,1358003630),(104475,1046,1357336648),(104695,1046,1356490615),(104714,1045,1357763473),(104852,1045,1357180728),(105009,1085,1355261359),(105174,1045,1357374201),(105434,1045,1357931841),(105434,1085,1355234805),(105477,1045,1356149974),(105500,1085,1355241535),(105538,1046,1357337253),(105599,1045,1357128144),(105599,1046,1357340265),(105622,1045,1357999624),(105652,1045,1357935432),(105732,1085,1355239355),(105762,1045,1358023463),(105799,1045,1355848790),(105922,1045,1357327887),(105924,1045,1357598333),(105969,1046,1355445453),(105983,1045,1357327960),(106155,1045,1356126442),(106232,1085,1355271240),(106483,1045,1356120555),(106698,1085,1355252463),(106751,1085,1355248836),(107103,1045,1357401659),(107252,1045,1357959302),(107261,1085,1355238833),(107333,1045,1357076486),(107358,1045,1357358334),(107378,1085,1355287498),(107386,1046,1357336441),(107482,1045,1357896299),(107555,1045,1357358916),(107636,1046,1357339772),(107649,1085,1355235486),(107672,1046,1357254432),(107717,1046,1356717988),(107941,1085,1355247930),(107964,1045,1355515618),(108021,1085,1355238551),(108044,1045,1355178532),(108070,1045,1357371512),(108070,1085,1355248822),(108157,1045,1357658195),(108201,1045,1357358847),(108337,1045,1357789170),(108380,1045,1357348615),(108387,1085,1355285918),(108443,1046,1357324157),(108446,1045,1357698062),(108478,1045,1357970328),(108570,1046,1356596046),(108599,1045,1357090382),(108603,1045,1355510312),(108620,1045,1357960241),(108685,1045,1357693245),(108811,1085,1355269094),(108851,1045,1357362048),(108897,1085,1355242977),(109000,15056,1355239536),(109240,1045,1357250947),(109307,1045,1355518401),(109320,1045,1356618574),(109332,1045,1357251508),(109332,1227,1357251506),(109377,1046,1357249343),(109420,1046,1357244254),(109420,1085,1355237126),(109436,1045,1357954338),(109442,1045,1357934171),(109475,1085,1355239290),(109595,1045,1357327687),(109595,1227,1357327686),(109794,1085,1355240208),(109809,1045,1357077027),(109879,1045,1357358173),(110122,1045,1357335463),(110316,1046,1357326911),(110369,1045,1355820752),(110390,1085,1355176470),(110500,1045,1357088578),(110557,1045,1357359728),(111153,1045,1357109811),(111701,1236,1357264457),(111901,1045,1355842942),(111911,1045,1357353501),(112108,1046,1357341499),(112265,1085,1355275848),(112293,1045,1357353034),(112887,1045,1355543245),(113114,1045,1357934413),(113428,1046,1357338754),(113996,1085,1355245176),(114022,1085,1355240494),(114042,1045,1358037495),(114213,1085,1355450604),(114558,1046,1355862014),(114561,1085,1355255732),(114650,1085,1355237644),(114722,1085,1355236726),(114989,1045,1357347660),(115402,1045,1358130161),(115472,1045,1357363889),(115535,1045,1356218517),(115599,1045,1357939316),(115633,1045,1357661972),(115862,1045,1357347842),(115884,1046,1357339998),(115909,1045,1356126442),(116112,1046,1357324104),(116113,1085,1355276076),(116176,1045,1357347525),(116206,1046,1357337128),(116206,1085,1355261085),(116275,1045,1357340903),(116275,1046,1357340888),(116308,1045,1357246052),(116328,1046,1357338971),(116328,1085,1355504860),(116454,1046,1355469732),(116516,1045,1355178686),(116516,1227,1355178684),(116667,1085,1355250618),(116749,1046,1357727030),(116847,1045,1357485968),(116915,1045,1357965851),(116915,1085,1355241247),(116960,1045,1358018433),(117074,1045,1358034159),(117226,1045,1355237842),(117226,1085,1355351946),(117270,1085,1355262372),(117272,1045,1355931587),(117443,1045,1355518110),(117443,1046,1357341250),(117469,1236,1355527566),(117518,1045,1355531728),(117592,1046,1355643194),(117624,1045,1357304042),(117700,1085,1355245437),(117717,1045,1357585789),(117739,1046,1357336710),(117739,1085,1355253805),(117804,1085,1355249794),(117814,1046,1357339732),(117932,14,1356313184),(117939,1045,1357248329),(117975,1045,1357345971),(118164,1085,1355206605),(118208,1045,1355511565),(118353,1045,1357179882),(118368,1045,1357933933),(118376,1045,1357598026),(118786,1085,1355257579),(118812,1236,1357934261),(118853,1045,1357935615),(118856,1045,1358028854),(118862,1046,1357337192),(118865,1046,1357339677),(118960,1045,1355181906),(119003,1045,1357763408),(119054,1085,1355249853),(119067,1045,1356189438),(119105,1045,1355506978),(119105,1085,1355235846),(119172,14,1357577170),(119220,1085,1355254372),(119440,1085,1355176526),(119456,1046,1357328946),(119558,1045,1357327876),(119558,1085,1355288838),(119665,1045,1355174788),(119681,1045,1357444301),(119715,1045,1355226397),(119821,1085,1355235826),(119864,1045,1357335536),(120192,1045,1357663212),(120192,1046,1357663390),(120263,1045,1357945222),(120328,1045,1357014360),(120408,1046,1357263045),(120408,1085,1355365275),(120411,1045,1358006025),(120418,1045,1357251407),(120502,1045,1356119607),(120533,1085,1355433062),(120729,1045,1358032360),(120831,1045,1357358122),(120840,11945,1357421431),(120887,1045,1355823911),(120893,1085,1355241411),(120926,1085,1355244259),(120933,1045,1357366371),(120986,1045,1358007412),(120992,1046,1357337566),(121013,1085,1355240693),(121238,1045,1357277078),(121238,1085,1355284402),(121332,1045,1355223373),(121340,1045,1357813057),(121412,1045,1358089307),(121441,1085,1355331525),(121611,1045,1357912804),(121611,1046,1357912545),(121821,1045,1357955312),(121821,1236,1357348735),(124535,1046,1357337177),(125335,1045,1357576199),(127609,1085,1355247739),(128963,1045,1357582918),(129520,1046,1357328886),(129536,1045,1357826106),(130426,1045,1356199712),(130776,1045,1357944490),(131540,1045,1357311013),(132948,1045,1357335587),(138356,1045,1358055874),(138384,1046,1357340930),(140571,1045,1357325976),(140852,1236,1357327531),(141716,1045,1356822130),(143358,1085,1355251320),(144171,1046,1358065440),(146887,1236,1355773297),(147393,1045,1357327288),(147959,1046,1357326863),(148934,1045,1355197688),(149254,1046,1357861468),(150382,1045,1357843074),(151677,1046,1355502725),(151677,1085,1355250409),(152224,1046,1356718675),(152406,1045,1355543223),(157491,1085,1355243069),(158624,1045,1357249036),(160742,1045,1356402423),(160742,1046,1357326869),(161077,1045,1357956223),(162536,1085,1355325535),(164371,1045,1358099362),(165072,1045,1357364943),(167776,1045,1358048225),(167776,1046,1355675188),(168422,1045,1357837623),(173276,1045,1357353940),(173349,1085,1355238859),(174473,1045,1357947405),(178824,1045,1356568956),(179581,1045,1358005092),(180154,1045,1357959875),(180154,1046,1357254300),(180241,1045,1355524534),(180429,1085,1355257224),(181608,1085,1355237302),(191991,1045,1357328042),(191991,1236,1357323359),(193707,1045,1357327916),(193707,1046,1356363176),(197056,1045,1355808018),(197998,1085,1355242339),(201178,1046,1355822300),(202156,1045,1357348360),(202510,1045,1357930431),(202510,1046,1357930717),(202510,11820,1357830362),(202510,11838,1357576998),(202510,11844,1357577078),(202510,11922,1357830745),(202510,11927,1357830739),(202510,11941,1357830741),(202510,11942,1357830747),(202510,11943,1357830750),(202510,11944,1357830757),(202510,12071,1357830752),(202510,12099,1357830755),(202510,12203,1357830743),(202510,12267,1357830737),(202510,12525,1355495941),(202510,14583,1355495959),(202510,14812,1355495961),(202510,14824,1355495591),(202510,14836,1355495567),(202510,14971,1355495531),(202510,15059,1355251532),(202510,15066,1355488587),(202510,15068,1355488718),(202510,15069,1355423078),(202510,15070,1355488712),(202510,15071,1355489848),(202510,15072,1355493618),(202510,15077,1355854574),(202510,15078,1355848986),(202510,15080,1355936526),(202510,15083,1355936357),(202510,15085,1356098016),(202510,15087,1356103930),(202510,15088,1356106482),(202510,15090,1357316938),(202510,15094,1357137075),(202510,15095,1357316988),(202510,15097,1357311951),(202510,15100,1357577365),(202510,15104,1357913256),(202510,15105,1357913254),(202510,15106,1357849914),(202510,15107,1357913249),(202510,15108,1357912992),(202510,15109,1357830901),(202510,15110,1357913244),(202510,15114,1357918242),(204834,1085,1355278283),(207074,1045,1357767425),(208630,1236,1357828461),(219503,1046,1355807516),(220941,1045,1357625319),(224918,1045,1358034344),(226479,1045,1357347642),(227737,1046,1357708115),(230668,1045,1357965396),(233341,1046,1357339861),(237398,1046,1357341179),(238948,1045,1357987761),(238948,1227,1357987760),(239627,1045,1357891831),(239772,1046,1357341118),(241170,1045,1358104727),(243090,1085,1355240441),(244092,1085,1355254613),(244108,1045,1357957012),(247328,1045,1357344742),(250808,1045,1357406034),(251560,1046,1357340059),(259616,1046,1357336140),(259658,1045,1358030601),(259668,1046,1357341195),(260011,1045,1357936174),(260011,1085,1355247020),(260011,1227,1357935976),(260017,1045,1357264425),(260017,1227,1357264424),(260022,1046,1357341508),(260022,1085,1355270793),(260553,1045,1357954491),(260573,1236,1357497436),(260587,1046,1357258273),(260611,1085,1355288927),(261402,1046,1357336864),(261457,1045,1358132681),(261644,1085,1355236650),(261660,1045,1358003922),(261795,1046,1357341461),(261921,1045,1357940833),(261992,1085,1355331459),(262035,15070,1355658712),(262269,1045,1358003562),(262580,1045,1357358687),(262601,1085,1355236412),(262609,1045,1357670060),(262621,1046,1357326734),(262640,1046,1355927461),(262658,1046,1357338720),(262661,1045,1357398380),(262689,1046,1357339302),(262731,1045,1357347806),(262924,1085,1355245634),(263226,1045,1357081948),(263227,1045,1358119398),(263227,1046,1356620044),(263306,1045,1357985382),(263428,1045,1358045108),(263551,15051,1355833857),(263671,1045,1357352909),(263673,1045,1357936660),(263820,1045,1357938231),(263941,1236,1357076893),(264039,1045,1355264627),(264039,1085,1355264733),(264043,1045,1357327919),(264113,1085,1355236250),(264139,1045,1357517494),(264156,1046,1356964686),(264160,1046,1357260446),(264349,1045,1357327732),(264426,1236,1357073766),(264432,1236,1357329500),(264554,1085,1355275221),(264566,1085,1355179803),(264616,1045,1357947546),(264616,1085,1355246447),(264631,1046,1357587785),(264737,1085,1355250961),(264746,1046,1357326913),(264893,1045,1357953692),(264893,1046,1357339090),(264949,1045,1357328096),(265167,1045,1357933157),(265253,1045,1357139014),(265268,1045,1357685426),(265342,1046,1357336988),(265404,1045,1355191039),(266873,1085,1355238047),(266900,1045,1357349817),(266927,1085,1355244715),(267094,1046,1357336406),(267410,1085,1355198294),(267504,1045,1357889970),(267504,1046,1357889699),(267851,1045,1355791399),(267851,1046,1355791364),(268032,1045,1357932945),(268032,1046,1357324118),(268053,1046,1357339443),(268081,1045,1357246333),(268097,1045,1357414730),(268156,1046,1357337403),(268289,1046,1357338353),(268352,1046,1357008930),(268500,1045,1357303293),(268513,1045,1357256437),(268523,1045,1356141006),(268537,1045,1355552118),(268537,1046,1357625659),(268887,1236,1357438317),(268946,1045,1357948686),(268979,1046,1357338202),(268979,1085,1355249284),(269044,1046,1357947051),(269052,1085,1355239475),(269284,1046,1356322678),(269475,1045,1357951552),(269638,1045,1357932673),(269741,1045,1357642357),(269773,1046,1357246922),(269841,1045,1357346835),(269862,1046,1358066346),(269886,1046,1357341215),(270006,1046,1356378198),(270025,1085,1355274848),(270046,1045,1357952599),(270046,1046,1357338602),(270063,1085,1355310371),(270096,1045,1356981931),(270164,1045,1357246532),(270203,1085,1355273565),(270260,1085,1355242655),(270329,1085,1355268389),(270381,1085,1355280126),(270622,1045,1357616800),(270624,1045,1358052937),(270810,1046,1357339730),(270940,1085,1355242439),(270968,1045,1357950396),(271033,1045,1357688123),(271140,1085,1355237212),(271366,1085,1355280424),(271423,1085,1355288937),(271470,1045,1357352695),(271479,1085,1355321729),(271554,1045,1357256571),(271569,1045,1355855996),(271583,1046,1357324763),(271591,1085,1355237456),(271822,1045,1355537104),(271822,1046,1357254427),(271877,1045,1357273546),(271947,1045,1357330761),(271975,1045,1357933631),(272014,1045,1357949279),(272042,1045,1356125747),(272089,1085,1355316533),(272116,1085,1355237566),(272191,1046,1357208444),(272219,1045,1357077449),(272346,1045,1357947090),(272431,1085,1355263211),(272443,1085,1355250874),(272586,1085,1355253133),(272715,1045,1357997434),(272765,1085,1355330308),(273001,1085,1355241189),(273016,1085,1355257280),(273020,1085,1355248858),(273035,1045,1357775944),(273035,1085,1355265834),(273088,1085,1355245426),(273285,1236,1357328678),(273329,1045,1357244556),(273416,1085,1355244797),(273463,1046,1357934198),(273501,1046,1357339307),(273502,1046,1357336086),(273567,1085,1355400973),(273727,1045,1357938563),(273751,1045,1357087694),(273827,1045,1357351070),(273857,1045,1357352407),(273900,1045,1357433719),(273900,1046,1356455486),(274068,1045,1358008780),(274137,1236,1357074061),(274153,1040,1357340606),(274153,1042,1357340577),(274153,1045,1357340607),(274153,1046,1357340578),(274196,1045,1357619580),(274196,1046,1357619575),(274208,1045,1357959461),(274230,1045,1357336813),(274250,1046,1357337155),(274366,1045,1358014301),(274548,1046,1357675026),(274624,1046,1357327904),(274661,1045,1358023593),(274710,1045,1357936132),(274710,1236,1357331751),(274713,1045,1358013440),(274721,1045,1355510999),(274721,1046,1357336104),(274731,1085,1355260942),(274741,1045,1357286498),(274754,1046,1357336985),(274769,1085,1355260663),(274794,1085,1355247478),(274815,1045,1357936454),(274818,1045,1356489488),(274851,1045,1357611242),(274863,1085,1355259727),(274983,1045,1357582031),(274983,1236,1357581533),(275075,1046,1357339579),(275198,1045,1358164142),(275346,1045,1358125779),(275410,1045,1357325272),(275470,1045,1357950162),(275499,1046,1357338049),(275741,1045,1357932888),(275741,1085,1355371987),(275752,1045,1358104481),(275915,1085,1355251086),(276015,1045,1357932447),(276080,1045,1357149062),(276080,7628,1357149323),(276206,1045,1357854422),(276276,1085,1355243984),(276284,1045,1357584421),(276300,1045,1357250507),(276337,1045,1355530838),(276357,1045,1358091439),(276402,1085,1355240407),(276537,1045,1356122714),(276537,1085,1355238269),(276632,1085,1355235079),(276786,1046,1357326769),(276991,1045,1357599091),(277225,1045,1357950967),(277441,1085,1355250152),(277776,1040,1357934070),(277776,1042,1357933829),(277776,1045,1357934073),(277879,1045,1357348264),(279023,1045,1356134460),(279040,1045,1358027009),(279137,1045,1357358395),(279290,1046,1357336545),(279349,1045,1355524326),(279415,1085,1355257372),(279461,1046,1357341054),(279549,1045,1357314987),(279549,1046,1357339517),(279660,1045,1357589021),(279772,1045,1355289456),(279924,1045,1358052976),(279938,1045,1357140555),(279938,1046,1356464558),(279938,1227,1357140554),(279938,1236,1357680104),(280049,1045,1357946652),(280224,1046,1357340563),(280266,1042,1357341396),(280266,1046,1357341527),(280439,1046,1357338700),(280461,1046,1355917340),(280479,1085,1355239096),(280533,1046,1357337476),(280572,1045,1357663866),(280661,1045,1358023751),(280668,1085,1355256401),(280827,1045,1356203966),(280827,1085,1355257010),(280833,1085,1355268872),(280864,1085,1355240226),(281032,1046,1357336768),(281064,1085,1355259159),(281174,1085,1355242328),(281207,1045,1357939209),(281207,1085,1355280751),(281214,1045,1357259907),(281239,1039,1357330409),(281239,1046,1357330409),(281263,1046,1357339986),(281461,1046,1357329000),(281461,1236,1357329071),(281466,1085,1355235960),(281481,1046,1357338135),(281483,1046,1355309343),(281578,1045,1357075939),(281607,1046,1357340525),(281636,1085,1355251463),(281842,1085,1355243550),(281921,1045,1357081417),(282023,1085,1355277136),(282052,1085,1355235078),(282056,1045,1357347333),(282068,1046,1357339776),(282068,1085,1355361925),(282095,1045,1357348073),(282112,1045,1358028313),(282161,1085,1355265660),(282301,1045,1357091251),(282352,1046,1357338321),(282352,1085,1355288283),(282357,1045,1357676537),(282443,1085,1355237923),(282454,1045,1357445763),(282454,1085,1355254329),(282464,1085,1355294640),(282481,1045,1357249962),(282492,1236,1357324059),(282536,1045,1357931774),(282667,1045,1357947744),(282700,1045,1355923747),(282841,1040,1357147292),(282841,1045,1357147293),(282851,1085,1355247817),(283084,1045,1357945054),(283180,1085,1355237772),(283384,1085,1355293153),(283388,1045,1357294087),(283447,1045,1355629526),(283447,1227,1355629524),(283447,1236,1355629491),(283494,1045,1357698559),(283497,1045,1355252621),(283518,1045,1357934335),(283529,1046,1357323669),(283575,1045,1357677928),(283606,1045,1357944173),(283606,1227,1355689210),(283649,1045,1358094747),(283649,1046,1358094740),(283845,1045,1357355315),(284023,1046,1357337523),(284184,1045,1357927796),(284370,1045,1357398679),(284391,1045,1355811289),(284611,1046,1357326883),(284722,1045,1357940857),(284757,1045,1355809915),(284832,1045,1357663830),(284925,1045,1357130582),(285054,1045,1357253439),(285054,1046,1357337695),(285060,1045,1355512634),(285123,1045,1357249896),(285136,1045,1356377196),(285374,1045,1357352937),(285377,1045,1357932609),(285377,1046,1356488092),(285388,1045,1357358421),(285403,1085,1355242524),(285514,1045,1357933712),(285514,1046,1357934165),(285585,1045,1357949148),(285611,1045,1357312012),(285767,1045,1355854208),(285886,1045,1358039790),(285917,1236,1357180289),(285928,1085,1355272233),(286027,1045,1355193026),(286031,1045,1357347022),(286095,1045,1358139071),(286226,1045,1357952117),(286259,1085,1355249853),(286347,1045,1357477745),(286347,1046,1356527360),(286433,1045,1357839088),(286559,1045,1356131034),(286665,1045,1357346669),(286951,1045,1357139763),(286983,1085,1355249833),(287017,1236,1355938985),(287021,1046,1357338762),(287021,1236,1356572507),(287080,1045,1356565567),(287118,1045,1357765688),(287253,1085,1355254840),(287409,1085,1355241935),(287517,1045,1357934242),(287619,1045,1358122313),(287621,1045,1357335549),(287668,1085,1355236720),(287809,1045,1358117834),(287809,1227,1358117832),(287927,1046,1357337546),(288126,1045,1357942135),(288182,1045,1355274635),(288272,1046,1357267635),(288273,1045,1357947941),(288333,1040,1357075961),(288333,1045,1357075889),(288351,1085,1355277611),(288561,1045,1355806023),(288652,1085,1355253864),(288837,1085,1355241052),(289009,1085,1355183525),(289056,1046,1357336955),(289148,1046,1357360158),(289569,1085,1355250631),(289889,1085,1355290173),(290106,1045,1355855034),(290108,1085,1355279962),(290116,1045,1357246125),(290123,1045,1357332861),(290123,1046,1356007812),(290189,1045,1356173159),(290189,1085,1355315765),(290215,1085,1355236512),(290228,1046,1356088159),(290239,1045,1358158824),(290505,1085,1355237804),(290611,1085,1355279638),(290740,1045,1358040456),(290811,1046,1357340698),(291038,1045,1357933879),(291158,1045,1357148540),(291441,1045,1357658080),(291579,1045,1358005701),(291798,1045,1358052201),(291844,1045,1357663479),(291873,1045,1355264722),(292210,1236,1357407544),(292376,1045,1357150039),(292404,1085,1355237559),(292486,1046,1357743614),(292524,1045,1357248980),(292709,1045,1357255586),(292742,1045,1358006450),(292743,1085,1355240609),(292754,1045,1357245653),(292939,1085,1355272742),(292971,1085,1355419377),(293020,1045,1358016387),(293074,1085,1355248928),(293370,1045,1357075065),(293800,1046,1357340541),(293908,1045,1358047208),(293983,1045,1355509523),(294205,1046,1357606780),(294256,1046,1357338303),(294256,1085,1355235968),(294467,1045,1355883858),(294495,1040,1357937940),(294495,1045,1357937942),(294495,1085,1355246618),(294959,1045,1357978240),(295448,1085,1355241350),(295686,1045,1357942245),(295758,1045,1357327828),(295866,1085,1355249935),(295994,1045,1357935540),(296053,1045,1357244611),(296464,1046,1357479958),(296474,1046,1357340709),(296474,1085,1355267577),(296625,1046,1357341361),(296718,1045,1357689099),(296794,1045,1355511807),(297060,1085,1355272900),(297277,1045,1357942990),(297277,1046,1357340975),(297372,1042,1357337898),(297372,1046,1357337952),(297392,1085,1355235717),(297420,1045,1358023501),(297420,1085,1355263838),(297543,1045,1357347870),(297699,1045,1357970409),(298007,1045,1357322146),(298154,1045,1357673012),(298216,1045,1355247039),(298237,1046,1357259236),(298272,1046,1355761688),(298276,1045,1356144877),(298455,1045,1357406395),(298563,1045,1357405827),(298790,1045,1355860902),(298846,1085,1355250814),(298882,1045,1357398182),(298915,1045,1357358651),(298915,1046,1357358583),(299027,1046,1357337109),(299080,1045,1355932633),(299208,1085,1355251975),(299435,1236,1357508674),(299528,1046,1357726083),(299562,1040,1357337405),(299562,1045,1357337406),(299562,1046,1357337509),(299671,1045,1355514250),(299842,1042,1357663671),(299842,1045,1357663672),(299842,1046,1357663620),(299993,1045,1358097605),(300030,1045,1357779286),(300249,1045,1358097660),(300308,1045,1357956552),(300419,1045,1357369688),(300515,1045,1358011223),(300575,1045,1356136686),(300976,1085,1355269729),(301114,1045,1355888657),(301114,1085,1355236067),(301258,1046,1357337277),(301280,1085,1355248146),(301466,1045,1357340841),(301655,1045,1358001407),(301679,1045,1357948072),(301753,1045,1357335071),(301861,1045,1357921591),(301920,1045,1357391840),(301944,1045,1357874870),(302031,1045,1355508872),(302570,1046,1357467914),(302741,1040,1357663866),(302741,1042,1357663852),(302741,1045,1357664035),(303740,1085,1355289732),(303931,1045,1356121244),(304035,1045,1355509371),(304178,1045,1357327518),(304260,1085,1355245914),(304473,1046,1357336242),(304586,1046,1357326873),(304628,1085,1355329976),(305063,1085,1355239081),(305135,1045,1357358758),(305136,1045,1358049582),(305296,1085,1355240029),(305538,1045,1357607217),(305554,1045,1358009628),(305610,1046,1356833474),(305983,1046,1357861490),(306056,1045,1357966906),(306131,15094,1357258190),(306166,1045,1357966690),(306339,1045,1357331717),(306543,1045,1356740641),(306558,1045,1357075787),(306580,1045,1357591764),(306635,1045,1358021205),(306864,1045,1357365638),(307014,1085,1355276531),(307065,1045,1357601573),(307621,1045,1357413019),(307621,1085,1355243056),(307633,1045,1357940061),(307715,1046,1357340874),(307726,1085,1355317182),(308109,1085,1355236394),(308301,1045,1357380211),(308301,1046,1357720667),(308301,1236,1357380222),(308570,1045,1356987236),(308575,1045,1357245542),(308585,1045,1357327918),(308662,1045,1357370424),(309161,1045,1358101976),(309189,1045,1355512667),(309195,1045,1355177258),(309366,1085,1355268322),(309369,1045,1357951410),(309495,1045,1355225804),(309554,1045,1357949354),(309882,1046,1357339733),(309974,1045,1357953082),(310028,1045,1357335609),(310728,1046,1357323640),(310737,1045,1357964420),(310783,1085,1355236746),(310928,1046,1356497522),(311074,1045,1357327738),(311383,1045,1357309815),(311503,1045,1357076030),(311726,1045,1355845394),(312030,1045,1357266063),(312030,1227,1357266062),(313061,1045,1356569678),(313061,1227,1356569676),(313345,1045,1357934052),(313677,1045,1355585699),(313795,1085,1355280359),(313999,1045,1357335528),(314004,1040,1357337064),(314004,1042,1357337306),(314004,1045,1357337065),(314004,1046,1357337308),(314076,1045,1356122679),(314210,1045,1357365168),(314210,1085,1355237276),(314232,1045,1357962897),(314237,1045,1357338273),(314237,1046,1357338328),(315608,1045,1357353484),(315624,1085,1355246999),(315731,1085,1355242469),(315921,1085,1355250404),(316110,1085,1355256267),(316149,1085,1355237380),(316164,1045,1357250481),(316328,1046,1355389418),(316417,1045,1355523858),(316449,1046,1357338818),(316613,1085,1355267201),(317073,1045,1357957237),(317073,1085,1355242117),(317567,1045,1357588410),(317931,1085,1355238773),(318593,1046,1357338372),(318693,1045,1357945987),(318693,1046,1357335938),(319093,1236,1357246937),(319260,1045,1357369061),(319338,1085,1355236674),(319385,1085,1355279039),(319475,1236,1355182537),(319526,1045,1357840515),(319646,1085,1355238404),(319839,1045,1357352538),(319984,1045,1357760981),(320672,1046,1357324104),(320983,1045,1357365520),(321209,1045,1357956769),(321374,1236,1358113014),(321431,1046,1357337551),(321578,1045,1357348151),(322018,1046,1357341024),(322038,1045,1357932190),(322056,1045,1358053723),(322160,1085,1355237232),(322198,1085,1355271564),(322205,1045,1357935886),(322746,1046,1357340432),(322746,1085,1355267321),(322831,1045,1356574965),(322831,1236,1356574988),(322877,1236,1357157551),(322894,1045,1357253453),(322999,1236,1357227358),(323228,1085,1355235967),(323494,1236,1355209237),(323588,1045,1357822618),(323671,1045,1357359484),(323754,1236,1355175596),(323810,1045,1355812568),(323849,1085,1355311114),(324272,1046,1357249332),(324425,1045,1355190908),(324425,1227,1355190903),(325069,1045,1357737293),(325352,1227,1357100811),(325482,1045,1358161401),(325755,1045,1357075432),(325816,1236,1357438831),(325949,1045,1355511151),(326096,1045,1357944545),(326206,1085,1355236710),(326327,1045,1357369213),(326327,1046,1357369135),(326504,1085,1355239214),(326764,1045,1357341898),(327068,1085,1355258411),(327222,1045,1357089430),(327222,1046,1357340327),(327240,1045,1356738796),(327240,1227,1356738795),(327278,1045,1357377806),(327649,1045,1356026418),(327980,1045,1358112539),(328030,1085,1355239498),(328037,1085,1355242420),(328128,1046,1357802704),(328459,1085,1355277969),(328565,1085,1355235984),(328761,1085,1355238578),(328767,1045,1357081845),(328777,1045,1357933922),(328910,1236,1355253824),(328963,1046,1357339870),(328982,1045,1357365744),(329363,1045,1357322141),(329552,1236,1357397543),(329593,1045,1357355162),(329611,1046,1357336625),(330824,1085,1355252581),(331138,1085,1355244408),(331710,1045,1357358696),(331710,1085,1355243670),(331874,1045,1357620465),(331903,1045,1357244716),(331918,1045,1357357853),(332148,1045,1357328028),(333011,1045,1357251729),(333016,1045,1357931952),(333272,1085,1355274499),(333507,1045,1357251010),(333581,1045,1355811342),(333845,1045,1356136842),(334064,1085,1355291308),(334238,1046,1357673407),(334268,1046,1357328367),(334292,1045,1355936731),(334292,1227,1355936729),(334386,1085,1355237292),(334454,1045,1357949440),(334454,1046,1356408204),(334728,1045,1357335585),(334956,1045,1357321251),(334964,1046,1357324103),(335311,1085,1355243793),(335521,1085,1355239651),(335746,1085,1355241382),(335979,1085,1355257940),(336136,1046,1356802413),(336443,1045,1358018285),(336813,1045,1357258766),(336945,1085,1355248279),(337181,1045,1358114596),(337181,1227,1358114610),(337223,1085,1355261545),(337268,1085,1355244254),(337520,1045,1358097737),(337527,1236,1357852806),(337555,1045,1355834215),(337732,1085,1355275939),(337814,1085,1355252815),(338032,1085,1355239846),(338226,1045,1355536271),(338699,1236,1357941951),(338775,1045,1357359528),(338994,1046,1357341083),(339007,1045,1355816303),(339007,1227,1355816302),(339077,1046,1357337634),(339077,1085,1355246075),(339217,1045,1356127710),(339217,1085,1355366767),(339779,1046,1355494354),(339830,1045,1357992696),(339830,1046,1357817404),(339928,1085,1355447569),(339968,1236,1357945151),(340024,1045,1358026496),(340239,1045,1355507232),(340257,1085,1355243870),(340300,1085,1355333820),(340392,1085,1355270896),(340423,1085,1355284438),(340785,1045,1357934475),(340870,1045,1356128381),(340973,1045,1357254420),(340979,1046,1356797311),(341014,1045,1357961789),(341268,1045,1357324484),(341445,1085,1355284989),(341567,1045,1357939552),(341603,1085,1355236235),(341746,1045,1355184977),(341800,1045,1357358325),(341815,1045,1357359645),(342911,1046,1357326886),(343053,1045,1357939732),(343093,1045,1357590648),(343262,1046,1357337995),(343476,1045,1357933726),(343659,1045,1357309026),(343784,1045,1357992201),(343840,1045,1357611479),(343908,1045,1357077613),(343996,1045,1355512534),(344002,851,1356042327),(344512,1045,1357617806),(344554,1045,1355512657),(344609,1045,1357320126),(344683,1045,1357368103),(344934,1046,1356503023),(344999,1045,1357935738),(345195,1045,1357078090),(345404,1046,1357205723),(345985,1045,1357347481),(345996,1045,1357342680),(346180,1046,1358104588),(346186,1045,1357091790),(346339,1046,1357868801),(346597,1045,1357613556),(346873,1045,1356661843),(346873,1046,1356509261),(346882,1045,1357359146),(346901,1045,1357278511),(346906,1045,1357266881),(346964,1046,1357089974),(347073,15094,1357482660),(347073,15097,1357301822),(347299,1085,1355267539),(347304,1045,1355186414),(347310,1046,1356390137),(347675,1045,1356126595),(347842,12081,1356539047),(348815,1045,1357228054),(348923,1236,1356056657),(349091,1045,1357931202),(350014,1045,1357078647),(350442,1045,1358011038),(350650,1085,1355235847),(350773,1045,1357605526),(350811,1046,1357336415),(350880,1085,1355239809),(350996,1236,1357423821),(351033,1236,1357094611),(351080,1046,1357324054),(351100,11945,1357101556),(351138,1045,1357361716),(352063,1045,1357933676),(352643,1045,1357914311),(352731,1045,1355810296),(352736,1046,1355576256),(352959,1045,1357769245),(353223,1045,1355731451),(353940,1046,1357339736),(354024,1045,1357249331),(354523,1045,1357655006),(354830,1045,1357955126),(354836,1045,1357417109),(354836,1046,1357341331),(354836,1085,1355268836),(354967,1085,1355238183),(355102,1045,1355872833),(355123,1085,1355255021),(355132,1045,1357081808),(355675,1085,1355273379),(355958,1045,1357245021),(355987,1045,1356121296),(356071,1045,1355179127),(356125,1085,1355236295),(356313,1045,1355505214),(356961,1045,1355837213),(357090,1085,1355241952),(357136,1085,1355240951),(357224,1040,1355849534),(357224,1045,1355849536),(357224,1046,1355849509),(357276,1236,1357246890),(357386,1045,1357494158),(357520,1085,1355268595),(357587,1085,1355247410),(357609,1046,1357337825),(357684,1085,1355258639),(357710,1085,1355256043),(358120,1085,1355302836),(358259,1045,1355813289),(358339,1236,1357328951),(358540,1045,1357081041),(358605,1085,1355239195),(359011,1045,1357334186),(359200,1045,1357328083),(359263,1046,1357337705),(359263,1085,1355242965),(359268,1046,1357326919),(359343,1045,1357227043),(359511,15074,1355636081),(359565,1045,1355507251),(359572,1045,1357307259),(359576,1045,1357383895),(359578,1085,1355237734),(359739,1045,1358036073),(359834,1045,1355841303),(359834,1227,1355841303),(359920,1045,1357100177),(359973,1045,1357365306),(359973,1236,1357250273),(359973,11945,1357249399),(360984,1046,1356793294),(361069,1045,1357347511),(361187,1085,1355237980),(361224,1045,1357359381),(361261,1045,1357948825),(361287,1046,1357340305),(361293,1085,1355356063),(361345,1085,1355257630),(361469,1085,1355359634),(361481,1045,1356126916),(361481,1085,1355264558),(361516,1045,1355555289),(361533,1045,1356976751),(361888,1045,1358082730),(362189,1046,1357339996),(362260,1045,1357078342),(362261,1045,1357345846),(362414,1085,1355264090),(362543,1045,1358001374),(362801,1045,1355743007),(363370,1045,1358110680),(363490,1045,1357401226),(363832,1045,1357338231),(363832,1046,1357338230),(363928,1045,1358005210),(364009,1045,1358051055),(364141,1046,1357341066),(364150,1045,1358019915),(364258,1085,1355236379),(364341,1045,1357335590),(364397,1045,1357679064),(364397,1227,1357679062),(364594,1045,1355196121),(365067,1045,1357346326),(365067,1046,1355698152),(365613,1045,1357073847),(365613,1227,1357073843),(365882,1045,1355847616),(365882,1085,1355241216),(365882,1227,1355847614),(366188,1085,1355234981),(366385,1046,1356809198),(366499,1045,1357603310),(366549,1045,1358117752),(366549,1046,1357869378),(366623,1046,1357340932),(366656,1045,1357277760),(366756,1045,1355828376),(366864,1046,1357340278),(366887,1045,1357076104),(366887,1227,1357076103),(367117,1046,1357340212),(367144,1045,1357374296),(367144,1046,1357807417),(367149,1046,1357336670),(367221,1046,1356486457),(367462,1085,1355241115),(367560,1045,1357775689),(367893,1046,1355382840),(368076,1045,1355954213),(368150,1045,1356985373),(368210,1045,1355890676),(368210,1085,1355239055),(368623,1045,1357312739),(368692,1046,1357760123),(369432,1045,1357327975),(369907,1045,1357328416),(369907,1227,1357328415),(370050,1085,1355240604),(370137,1045,1357252407),(370137,1236,1357252421),(370243,1045,1357944625),(370332,1085,1355236083),(370724,1045,1356972342),(371111,1046,1357336245),(371137,1045,1358011553),(371297,1045,1357578446),(371444,1236,1355187405),(371602,1045,1355834735),(371692,1045,1358002642),(371692,15069,1355587396),(371750,1085,1355239718),(371754,1085,1355238519),(371773,1045,1357352646),(371909,1046,1357723411),(371975,1045,1357954687),(372204,1045,1357272314),(372256,1085,1355193957),(372270,1045,1357348859),(372416,1045,1357256442),(372543,1085,1355247187),(372712,1046,1357340198),(372989,1045,1355176209),(373159,1045,1358106802),(373451,1045,1357933375),(373475,1045,1357245816),(373477,1085,1355275967),(373524,1045,1357244489),(373752,1085,1355235959),(373840,1045,1357360075),(373943,1045,1357229162),(374088,1045,1357665844),(374088,1227,1357665841),(374088,1236,1357665804),(374167,1045,1357355165),(374256,1040,1357338711),(374256,1042,1357338651),(374256,1045,1357338726),(374256,1046,1357339174),(374415,1045,1357335507),(374905,1046,1357336673),(374928,1045,1357317211),(375073,1045,1357353042),(375209,1045,1357690682),(375276,1045,1357319056),(376612,1046,1357339789),(376848,1045,1357075039),(376928,1045,1357628726),(377277,1085,1355243977),(377304,1045,1357810117),(377492,1045,1357328079),(377586,1046,1357339367),(377679,1046,1357336435),(377694,1085,1355260892),(377814,1045,1357761547),(377849,1045,1355522106),(378019,1046,1357337665),(378074,1236,1357531456),(378214,1045,1357003924),(378244,1045,1357337175),(378244,1046,1357337519),(378653,1045,1357652266),(378680,1045,1358124920),(378751,1046,1357336656),(378772,1085,1355236840),(378772,1236,1355236861),(379119,1046,1357338447),(379127,1045,1356725114),(379127,1046,1357341029),(379176,1045,1357996702),(379176,1085,1355239908),(379182,1045,1357867586),(379200,1085,1355235615),(379356,1045,1357796296),(380185,1045,1357609643),(380243,1045,1357664780),(380503,1085,1355457693),(380974,1045,1357977514),(381111,1085,1355243669),(381246,1045,1357995999),(381262,1085,1355236674),(381406,1046,1357324100),(381469,1045,1358002330),(381731,1045,1357247941),(381790,1045,1357388517),(381924,1085,1355248301),(381935,1085,1355351200),(382017,1085,1355267316),(382207,1045,1357291368),(382496,1046,1357339525),(382733,1085,1355236626),(382957,1046,1357341517),(383181,1045,1357359112),(383489,1045,1357951071),(383671,1045,1357947436),(383747,1085,1355254206),(384594,1085,1355248488),(384825,1085,1355246340),(384890,1045,1355809914),(385142,1045,1355878319),(385394,1045,1355592274),(385394,1046,1357335322),(385416,1046,1357326909),(385526,1085,1355252952),(385608,1085,1355284446),(386170,1045,1355875321),(386170,1046,1357340164),(386467,1045,1355830934),(386801,1236,1355831977),(386870,1045,1356392296),(386870,1227,1356392295),(386917,1045,1357347512),(387021,1045,1355501080),(387495,1085,1355242242),(387684,1045,1358107626),(387684,1236,1358107597),(387727,1045,1357079353),(387929,1045,1357768429),(388006,1085,1355243453),(388023,1045,1357244858),(388049,1045,1357606220),(388215,1045,1357831797),(388215,1046,1357831819),(388215,1236,1357666997),(388215,15035,1355244595),(388215,15091,1356620005),(388550,1085,1355243565),(388733,1045,1356128459),(388763,1227,1357081000),(388817,1046,1357337827),(389356,1085,1355238741),(389815,1045,1357936413),(390277,1045,1356123893),(390326,1046,1358065760),(391466,1045,1357327693),(391900,1045,1357006688),(391997,1045,1357527377),(392473,1045,1356973651),(392473,1227,1356973649),(392473,1236,1356973642),(393326,1045,1357942003),(393577,1046,1357337870),(393590,1046,1357337756),(394637,1085,1355260082),(394653,1046,1356181514),(394809,1045,1355516015),(394865,1085,1355241295),(395007,1045,1355525615),(395007,1085,1355277977),(395017,1045,1357322301),(395174,1085,1355241414),(395300,1085,1355258662),(395300,1236,1356392002),(395514,1085,1355248236),(395739,1045,1355182834),(395739,1085,1355182854),(396084,1045,1357247658),(396088,1236,1357138250),(396334,1045,1357954950),(396345,1045,1355838378),(396345,1227,1355838377),(396419,1045,1357943755),(396419,1046,1357338394),(396636,1045,1356194763),(396982,1045,1358008379),(397031,1045,1355824172),(397113,1046,1357338996),(397186,1085,1355409726),(397208,1045,1357328566),(397213,1085,1355238166),(397334,1046,1357337776),(397350,1045,1357352709),(397418,1045,1355631882),(397467,1045,1357345242),(397587,1045,1357245119),(397695,1045,1357955839),(397848,1045,1355843218),(398399,1045,1357965542),(398470,1045,1357672561),(398519,1046,1357339523),(398727,1045,1357681690),(398752,1045,1357358127),(398871,1045,1357316240),(398940,1046,1357339145),(399561,1045,1357353404),(399992,1085,1355251803),(400225,1045,1357353872),(400229,1045,1358053362),(400758,1045,1357324082),(400799,1045,1357252991),(400921,1045,1357688584),(400958,1046,1356941783),(401262,1085,1355237177),(401299,1085,1355269162),(401331,1045,1357944243),(401504,1085,1355235632),(401582,1045,1357664594),(401600,1045,1357333021),(401604,1045,1357348255),(401622,1045,1357314414),(401721,1045,1357672536),(402309,1040,1357341123),(402309,1045,1357370940),(402309,1046,1357341118),(402309,1236,1357370816),(402847,1046,1356649705),(403018,1045,1355509499),(403135,1085,1355237300),(403983,1085,1355269027),(404411,1045,1357606138),(404411,1085,1355238327),(404576,1045,1356310005),(404649,1085,1355472321),(404795,1045,1357498313),(404953,1046,1356172201),(404962,1046,1356641429),(405106,1045,1357345009),(405224,1045,1357610895),(405671,1046,1357337989),(405690,1046,1356335318),(405804,1045,1358043278),(406119,1045,1355516902),(406290,1045,1355812968),(406514,1085,1355247741),(407044,1085,1355257810),(407457,1045,1357328040),(407824,1045,1358008402),(407883,1040,1357931765),(407883,1042,1357931688),(407883,1045,1357932453),(407975,1085,1355235861),(408122,1045,1357385176),(408216,1045,1356118989),(408216,1046,1356570111),(408230,1045,1355869842),(408367,1045,1358003739),(408386,1085,1355270385),(408439,1045,1355809030),(408439,1236,1355809078),(408878,1045,1357323264),(408946,1045,1357935046),(409215,1045,1355517549),(409579,1046,1357338029),(409579,1085,1355431448),(409943,1046,1355414496),(410194,1045,1355236007),(410195,1045,1358117535),(410543,1045,1356366417),(410823,1045,1357327739),(410963,1045,1357938887),(411098,1046,1357497823),(411472,16,1357154392),(411472,926,1357583677),(411472,1045,1357668481),(411472,1046,1357668587),(411472,1061,1357583705),(411472,2260,1357156349),(411472,11950,1357750757),(411472,12258,1357743333),(411472,12489,1357752609),(411472,15035,1355248431),(411472,15094,1357156661),(411472,15095,1357596709),(411472,15097,1357661710),(411540,1045,1355175721),(411634,1046,1356848445),(411743,1045,1357257923),(412148,1236,1355174827),(412290,1045,1358042506),(412867,1045,1357378798),(412867,1046,1357203426),(412878,1236,1356002449),(413448,1045,1357941460),(413576,1045,1357347994),(413595,1085,1355239578),(413680,1045,1357273507),(413776,1045,1357674846),(413850,1045,1357244612),(414076,1046,1355608471),(414092,1045,1357592167),(414317,1045,1357315924),(414317,1227,1357315923),(414520,1045,1355806450),(414548,1085,1355239998),(414563,1046,1357340019),(414598,1085,1355241758),(414602,1046,1357339601),(414614,1045,1355518536),(414675,1045,1357353552),(415014,1045,1355839947),(415049,1046,1357341086),(415132,1085,1355241388),(415962,1045,1355863856),(415962,1227,1355863855),(416411,1045,1357948896),(416456,1045,1358049812),(416763,1085,1355236443),(416850,1045,1357943020),(416853,1045,1357331607),(416856,1046,1357332306),(417067,1085,1355286474),(417995,1085,1355423453),(418109,1045,1358075108),(418406,1046,1357249332),(418477,1045,1355201997),(418505,1046,1357116813),(418769,1085,1355250643),(419383,1045,1357135731),(419591,1046,1355176171),(419843,1046,1357249340),(419921,1045,1357951708),(420668,1045,1357957782),(420668,1046,1357338894),(420682,1085,1355247673),(420733,1045,1357074069),(420780,1085,1355252823),(421068,1045,1355508829),(421194,1045,1358008435),(421617,1045,1357951431),(421878,1046,1355667050),(422307,1085,1355266059),(422801,1045,1356537671),(422970,1046,1357338529),(423268,1045,1355511243),(423628,1045,1357353913),(423628,1236,1357353954),(423765,1046,1356676328),(424150,1045,1357961432),(424795,1045,1357359843),(424864,1045,1357378359),(424936,1045,1357720167),(425003,1045,1356124418),(425106,1045,1355845584),(425540,1045,1357780777),(425540,1085,1355271273),(425593,1046,1357324100),(425859,1236,1355239133),(425929,1085,1355236197),(425954,1046,1357340093),(426520,1045,1357081187),(426781,1045,1357851998),(427291,1045,1357624550),(427331,1045,1357948011),(427438,1045,1357952903),(427438,1085,1355281363),(427512,1045,1356127602),(427575,1236,1357076749),(427721,1046,1357337060),(427845,1045,1357375350),(427845,1046,1357295635),(427940,1045,1357685281),(428007,1045,1355828838),(428223,1085,1355241507),(428242,1045,1357609624),(428367,1045,1355812434),(428367,1085,1355269899),(428392,1045,1357944694),(428474,1046,1357339149),(428629,1045,1357366757),(428634,1046,1356829720),(428649,1046,1357339487),(428666,1045,1357347810),(428743,1085,1355274985),(428875,1045,1355192884),(429250,1085,1355238102),(429729,1085,1355256236),(429757,1085,1355281141),(429773,1045,1357996369),(429821,1085,1355238223),(430169,1085,1355245369),(430290,1045,1357363855),(430556,1085,1355236879),(430672,1045,1355818423),(430680,1040,1355821331),(430680,1045,1357932562),(431544,1085,1355241127),(431670,1046,1357326873),(432142,1045,1358056361),(432415,1045,1355233556),(432915,1045,1357248334),(433036,1045,1357665132),(433036,1085,1355279370),(433331,1046,1357337842),(433331,1085,1355252907),(433633,1045,1357321913),(433672,1046,1357474786),(434100,1236,1355274710),(434355,1085,1355236345),(434424,1085,1355270375),(434437,1045,1357668527),(434528,1085,1355245499),(434586,1042,1357704830),(434586,1045,1357705184),(434715,1046,1357256143),(434948,1046,1357338840),(435280,1085,1355422757),(435323,1045,1357400917),(435378,1085,1355268479),(435535,1045,1357935916),(435535,1046,1357747546),(436115,1085,1355237210),(436258,1085,1355280362),(436479,1045,1357356942),(436551,1045,1357940920),(436962,1085,1355243368),(437081,1045,1357943643),(437165,1046,1357341262),(437247,1045,1357365107),(437313,1085,1355247202),(437490,1045,1357344475),(437736,1046,1357326908),(437826,1085,1355251748),(437865,1045,1356654311),(437874,1045,1357352790),(437993,1045,1357381185),(438281,1085,1355266680),(438514,1045,1357934241),(438573,1045,1357615427),(438748,1045,1357352415),(438968,1085,1355183013),(439248,1045,1358034187),(439248,1227,1358034186),(439428,1046,1357340226),(439595,1045,1357959216),(439762,1085,1355244939),(440145,1085,1355238682),(440175,1046,1357337259),(440175,1085,1355238764),(440194,1046,1357336406),(440247,1045,1357790816),(440535,1085,1355343662),(440624,1046,1355866498),(440684,1236,1357157084),(440768,1085,1355256733),(440802,1045,1357352481),(440902,1045,1357503389),(440988,1085,1355238786),(441079,1045,1357944764),(441093,1045,1355267745),(441109,1085,1355263364),(441245,1045,1358017760),(441251,1045,1357940615),(441639,1045,1357084544),(441639,1227,1357084790),(441785,1046,1357337702),(441983,1085,1355238812),(442053,1045,1357332754),(442298,1085,1355354777),(442383,1045,1357082402),(442442,1085,1355236633),(442539,1045,1357076002),(442889,1045,1357244408),(442889,1227,1357244407),(443050,1045,1357338221),(443050,1046,1357338278),(443088,1045,1357359270),(443088,1236,1355952927),(443453,1045,1357672317),(443777,1085,1355232296),(443830,1045,1357327866),(443843,1045,1357777128),(443920,1045,1357353425),(443920,1236,1357353200),(444040,1045,1358045119),(444094,1045,1357384918),(444094,1085,1355240883),(444282,1046,1356827933),(444378,1045,1357348332),(444452,1085,1355506165),(444523,1045,1358139286),(444684,1045,1357353719),(444785,1085,1355275650),(445065,1045,1357313388),(445139,1045,1357365465),(445648,1085,1355377026),(445649,1045,1357359812),(446406,1045,1357938070),(446458,1045,1357251915),(446467,1045,1356132771),(446467,1085,1355241539),(446784,1045,1357327678),(447006,1045,1357251280),(447006,1227,1357251280),(447052,1045,1355722453),(447184,1045,1357261054),(447274,1045,1355807593),(447278,1046,1357326881),(447280,1045,1357612635),(447290,1045,1357959429),(447316,1085,1355236337),(447467,1085,1355236808),(447621,1085,1355318824),(447860,1045,1357534640),(447945,1046,1357336040),(447977,1045,1357942707),(448490,1236,1357401139),(448573,1045,1357853301),(448631,1045,1357318365),(448631,1236,1357318387),(448848,1046,1357547897),(449158,1045,1355516842),(449453,1085,1355245765),(449561,1045,1357952076),(450035,1085,1355325710),(450420,1045,1357690376),(450866,1045,1357090197),(450919,1045,1358000200),(451034,1085,1355250785),(451412,1085,1355239330),(451737,1085,1355258918),(451814,1046,1357898823),(451868,1045,1357580026),(451868,1046,1357581016),(452117,1045,1355575536),(452326,1046,1357338772),(452440,1045,1357579578),(452469,1045,1357948317),(452469,1236,1357246096),(452867,1045,1355526794),(453171,1236,1357084486),(453193,1045,1357710994),(453193,1046,1356516893),(453845,1085,1355247984),(453881,1085,1355249070),(453934,1045,1357356845),(454237,1046,1357254574),(454238,1045,1357817517),(454700,1085,1355248670),(454765,1045,1357327801),(455193,1085,1355245403),(455228,1045,1357602304),(455409,1045,1357663698),(455526,1045,1357359369),(455599,1045,1357352484),(455878,1085,1355258968),(455925,1045,1357425949),(455937,1046,1357337731),(456042,1045,1357257967),(456154,1045,1357429722),(456857,1046,1357663481),(457149,1045,1356121626),(457149,1085,1355259862),(457161,1045,1356122303),(457416,1045,1356144899),(457416,1046,1357336690),(457608,1046,1357337812),(457642,1045,1355814253),(457676,1045,1357344819),(457779,1045,1355810869),(457946,1085,1355253259),(457970,1085,1355240233),(458176,1236,1355519487),(458204,1045,1356144371),(458425,1045,1357861143),(458584,1046,1357244341),(459094,1045,1357705882),(459225,1085,1355262862),(459288,1045,1357309093),(459664,1085,1355238035),(459709,1045,1357252234),(459709,1046,1357340099),(459756,1045,1357321631),(459803,1045,1356122366),(459922,1046,1357249584),(460072,1085,1355274077),(460299,1045,1357363894),(460778,1046,1356889904),(460853,1045,1357326296),(460853,1227,1357326295),(460889,1045,1357380542),(460906,1045,1357353315),(460906,1085,1355247696),(461273,1045,1358103385),(461284,1236,1357944149),(461334,1045,1357247853),(461412,1045,1355509208),(461580,1045,1355198133),(462129,1085,1355236796),(462210,1045,1357655911),(462508,1085,1355245067),(462830,1045,1357078974),(462903,1085,1355265928),(462988,1046,1357338807),(463277,1045,1358002066),(463277,1085,1355315388),(463577,1045,1355507882),(463983,1045,1357353119),(463996,1046,1357341358),(464005,1085,1355274673),(464040,1045,1357269640),(464101,1045,1357662456),(464111,1045,1357841279),(464160,1045,1358084365),(464390,1045,1357327891),(464390,1236,1357594859),(464873,1045,1357328112),(465100,1046,1357339055),(465123,1045,1357351189),(465149,1045,1357348030),(465449,1045,1357387465),(465502,1085,1355182572),(465765,1045,1357938316),(465765,1046,1357336172),(465939,1085,1355282574),(466228,1040,1355825515),(466228,1045,1355825516),(466347,1046,1357336344),(466366,1045,1357249594),(466577,1045,1357859887),(466577,1046,1357859704),(466740,1045,1357947701),(466806,1045,1358007096),(466975,1085,1355282027),(467005,1045,1357348051),(467237,1085,1355335038),(467317,1236,1355176072),(467456,1046,1357113923),(467533,1045,1357286348),(467759,1045,1355838615),(468113,1046,1357336582),(468146,1085,1355242381),(468338,1045,1357735589),(468338,1046,1357327716),(468436,1045,1355531791),(468436,1085,1355253799),(468487,1046,1357355607),(468666,1045,1357370866),(468710,1236,1355809086),(468867,1085,1355266805),(469102,1045,1357341923),(469398,1085,1355246274),(469402,1045,1358129839),(469402,1236,1356910693),(469541,1046,1357336569),(469606,1046,1357664733),(469705,1045,1357248688),(469756,1085,1355240803),(469766,1045,1357757383),(469956,1045,1357185191),(470111,1045,1357353258),(470363,1045,1357742415),(470441,1045,1357632977),(470493,1045,1357959287),(470493,1046,1357339412),(470981,1045,1355813645),(471040,1045,1357948115),(471424,1045,1357495843),(471691,1236,1357299819),(471700,1045,1356990920),(472507,1045,1357327885),(472597,1046,1357341285),(472618,1046,1355641410),(472656,1046,1357337326),(472690,1045,1357362190),(472698,1045,1357346661),(472911,1046,1357337657),(472956,1085,1355237910),(472969,1046,1357326901),(472969,1085,1355263673),(473000,1085,1355243369),(473104,1046,1357244568),(473391,1045,1357348228),(473401,1085,1355247175),(473449,1045,1357624952),(473683,1045,1357324621),(473764,1085,1355506957),(473859,1045,1357358888),(474142,1085,1355238802),(474235,1045,1357663471),(474235,1046,1357663312),(474255,1085,1355240128),(474267,1045,1357640633),(474321,1045,1357148554),(474402,1045,1357266474),(474419,1045,1355806621),(474499,1085,1355285415),(474563,1085,1355236089),(474619,1045,1357941577),(474630,1045,1357686443),(474698,1045,1358015127),(475031,1236,1355245748),(475126,1046,1357326882),(475224,1085,1355283846),(475312,1085,1355248875),(475705,1045,1357248088),(475705,1227,1357248086),(475824,1085,1355256155),(476147,1045,1357962299),(476523,1045,1357935383),(476581,1045,1357686484),(476912,1046,1357339492),(476912,1085,1355277194),(476988,1046,1356918297),(477197,1045,1357387118),(477215,1045,1355506739),(477285,1085,1355285329),(477327,1046,1357339857),(477632,1045,1357079067),(477852,1085,1355347488),(478040,1085,1355237121),(478143,1085,1355276671),(478195,1042,1357341088),(478195,1046,1357341090),(478218,1085,1355236355),(478345,1085,1355237003),(478610,1045,1355259742),(478610,1085,1355259719),(478783,1045,1357082469),(478862,1046,1357338619),(478884,1045,1357354380),(478884,1227,1357354378),(478975,1045,1357359873),(479133,1045,1355861950),(479299,1045,1357932733),(479299,1085,1355235513),(479358,1046,1357340017),(479464,1085,1355245445),(479778,1045,1357322132),(479778,1085,1355250194),(479795,1085,1355257988),(479870,1085,1355244920),(479951,1085,1355257961),(479975,1045,1355266521),(480145,1045,1358027136),(480145,1046,1357340721),(480208,1045,1355894759),(480208,1085,1355246293),(480268,1085,1355300235),(480273,1045,1357348251),(480373,1046,1357826268),(480561,1045,1355518133),(480561,1085,1355376741),(480657,1236,1355952453),(480896,1045,1357359734),(481005,1045,1358118205),(481035,1045,1357677748),(481297,1045,1357933863),(481297,1046,1355176339),(481651,1046,1356882663),(481670,1045,1358145343),(481670,1046,1358145191),(481670,1085,1355254321),(481899,1046,1357550182),(481978,1045,1355235041),(482252,1046,1356544147),(482288,1046,1357628275),(482829,1045,1355818121),(483063,1236,1357146021),(483142,1045,1355812952),(483289,1085,1355190968),(483635,1085,1355240356),(483750,1045,1355888936),(483801,1085,1355243275),(484505,1045,1357347962),(484505,1085,1355274888),(484543,1045,1357353493),(484543,1046,1357353327),(484557,1045,1355605014),(484570,1045,1357327865),(484570,1085,1355237074),(484571,1045,1355520873),(484620,1085,1355237951),(485010,1046,1357338396),(485024,1046,1357663185),(485044,1085,1355239325),(485064,1085,1355239646),(485374,1045,1358019630),(485564,1045,1357933807),(485564,1046,1357341008),(485608,1085,1355276811),(486130,1045,1357093658),(486608,1045,1358086633),(486858,1045,1357353707),(486993,1045,1357090337),(487505,1045,1356151641),(488339,1085,1355289379),(489793,1046,1357331547),(489793,1236,1357331427),(489817,1045,1357949237),(490305,1045,1357871841),(490665,1040,1355484678),(490665,1045,1355484650),(490809,1085,1355283604),(490849,1236,1355670542),(490933,1085,1355369416),(491213,1045,1357081814),(491426,1085,1355288661),(491778,1085,1355339090),(491850,1085,1355417102),(491860,1085,1355288978),(492126,15070,1355832890),(492344,1045,1355925557),(492536,1045,1355816088),(492647,1046,1356048577),(492771,1045,1357933744),(492846,1045,1355837272),(492880,1045,1358026431),(492880,7752,1358026296),(492901,1045,1357944885),(493076,1085,1355241960),(493274,1045,1357276461),(493616,1046,1357084003),(493801,1236,1355866363),(493844,1085,1355189713),(494266,1045,1357937483),(494466,1085,1355280779),(494668,1046,1355846376),(494854,1046,1357336402),(494903,1046,1357536237),(494962,1085,1355288788),(495240,1046,1357337082),(495284,1046,1357341277),(495384,1045,1357673538),(495438,1045,1355526199),(495829,1045,1357961909),(495829,1085,1355297230),(495864,1045,1357388776),(496188,1046,1357337009),(496472,1085,1355431833),(496751,1085,1355287392),(496786,1046,1357339068),(496858,1085,1355244900),(496898,1045,1357839367),(497044,1045,1357941422),(497194,1046,1357326897),(497248,1085,1355264035),(497387,1045,1355513359),(497415,1045,1357356589),(497488,1045,1355197286),(497512,1045,1355506424),(497808,1045,1358000493),(498159,1045,1355544953),(498159,1085,1355376657),(498159,1236,1355895732),(498353,1085,1355248070),(498390,1045,1357378231),(498548,1045,1357677840),(498699,1046,1357245929),(498723,1085,1355235972),(498782,1085,1355265651),(498792,1045,1358042268),(498838,1045,1357963416),(498904,1045,1356123949),(498920,1085,1355252698),(498972,1236,1357247467),(499197,1045,1357934911),(499197,1085,1355236398),(499431,1045,1355837239),(499431,1085,1355251147),(499654,1046,1357327161),(499734,1045,1357266801),(499759,1045,1355833498),(499850,1085,1355235818),(499928,1236,1357075955),(499931,1046,1357340336),(499945,1045,1357865095),(500093,1085,1355262289),(500172,1085,1355338049),(500179,1045,1355810488),(500464,1085,1355238893),(500610,1046,1357942281),(500900,1085,1355277316),(500914,1085,1355258234),(501270,1085,1355275854),(501402,1045,1357394691),(501436,1046,1357324745),(501537,1085,1355338240),(501579,1085,1355238143),(501640,1085,1355250648),(501814,1085,1355425955),(501965,1045,1357357276),(502079,1085,1355271904),(502114,1046,1357337435),(502322,1046,1357337563),(502405,1085,1355284707),(502415,1045,1357515021),(502417,1046,1356757820),(502659,1085,1355181320),(502714,1045,1357365791),(502741,1045,1356146194),(502741,1046,1357267238),(502793,1085,1355273834),(502801,1045,1358114815),(503004,1046,1357972619),(503159,1085,1355237750),(504294,1045,1357347154),(504410,1045,1355853169),(504498,1045,1357327769),(504533,1085,1355248187),(504734,1045,1358126530),(504798,1046,1357332342),(504798,1236,1357331299),(504874,1085,1355276686),(505032,1045,1357938335),(505223,1046,1355696400),(505235,1045,1357353332),(505308,1045,1357249121),(505360,1046,1357144106),(505360,1236,1357258750),(505382,1085,1355353460),(505428,1045,1357978118),(505428,1085,1355246438),(505644,1045,1355844218),(505644,1046,1357336879),(505644,1085,1355242350),(505740,1085,1355291348),(505898,1045,1356124670),(506327,1236,1357172203),(506692,1085,1355177555),(506887,1045,1356192869),(507113,1045,1357940332),(507280,1085,1355340020),(507395,1046,1357336962),(507601,1045,1357590654),(507601,1085,1355253043),(507712,1046,1357339840),(507839,1085,1355250979),(507880,1045,1357935219),(507880,1085,1355237391),(507945,1045,1357796975),(507957,1085,1355237379),(508226,1045,1357966534),(508545,1046,1357336898),(508616,1045,1357347676),(508647,1085,1355243989),(508755,1045,1357675304),(508945,1045,1357951626),(509061,1045,1357076955),(509061,1085,1355235270),(509216,1045,1358055529),(509229,1045,1355893564),(509231,1046,1355979448),(509231,1236,1357343768),(509253,1045,1357932588),(509506,1045,1358059468),(509592,1085,1355270059),(509663,1045,1358060028),(509704,1045,1357248906),(509704,1046,1357249325),(509749,1042,1357338195),(509749,1046,1357338197),(509815,1085,1355238002),(509905,1085,1355239756),(510072,1045,1357255467),(510078,1085,1355506256),(510125,1045,1357078845),(510125,1227,1356923613),(510125,1236,1357078753),(510446,1045,1357139605),(510573,1045,1357399915),(510573,1046,1355838004),(510903,1085,1355238707),(510977,1085,1355360659),(511251,1045,1357938932),(511339,1045,1357663345),(512214,1085,1355289608),(512230,1045,1357764013),(512359,1045,1357996364),(512621,1045,1357265454),(512683,1045,1357947082),(512747,575,1358012995),(512747,1046,1358013042),(512953,1045,1357252484),(513059,1045,1357933197),(513101,1045,1357073416),(513738,1040,1357336297),(513738,1045,1357946793),(513738,1046,1357336358),(514250,1045,1355812397),(514436,1045,1358074570),(514614,1045,1356226789),(514686,1085,1355272600),(514738,1085,1355236321),(514939,1085,1355184503),(514982,1045,1357669617),(515136,1045,1357306405),(516517,1045,1355541110),(516591,1045,1356134325),(516860,1085,1355260688),(516931,1045,1357370458),(517009,1085,1355360097),(517012,1085,1355243594),(517082,1236,1355811889),(517350,1045,1357936656),(517350,1046,1357336704),(517350,15070,1355514820),(517350,15107,1357936858),(517509,1046,1357336332),(517680,1045,1357322631),(517680,1046,1357324041),(517941,1045,1357687654),(518028,1085,1355269762),(518110,1046,1357340522),(519125,1040,1357095694),(519125,1045,1357095604),(519181,1045,1357383210),(519198,1045,1355258904),(519198,1085,1355237512),(519233,1045,1357256726),(519328,1045,1355506542),(519462,1046,1357337794),(519925,1045,1357364895),(519948,1045,1357365187),(520364,1085,1355272985),(520552,1045,1357971040),(520552,1236,1357971049),(520817,1085,1355248355),(520899,1045,1357338702),(520899,1046,1357338463),(520899,11876,1356129599),(522043,1045,1355834541),(522096,1085,1355235757),(522295,1045,1357243923),(522509,1236,1355842961),(522665,1045,1356123062),(522669,1236,1357088801),(522707,1085,1355237223),(522899,1085,1355240756),(522984,1085,1355265715),(523134,1236,1357239811),(523218,1045,1357327908),(523319,1046,1357937979),(523654,1045,1357108307),(523735,1045,1357675098),(523814,1045,1357177951),(523842,1085,1355266000),(523954,1046,1357337182),(524568,1045,1356116152),(524694,1045,1357942983),(525033,1045,1357328070),(525056,1045,1357415272),(525056,1085,1355338004),(525094,1045,1357245271),(525234,1045,1357337368),(525234,1046,1357337368),(525373,1046,1357254404),(525431,1045,1357958870),(526499,1046,1357339648),(526890,1045,1357305588),(527178,1045,1357933334),(527408,1045,1357359036),(528258,1045,1356244152),(528531,1236,1357362084),(528583,1045,1358007063),(528954,1045,1355706375),(528998,1042,1357936800),(528998,1045,1357936802),(529253,1045,1357076769),(529686,1045,1357756766),(529751,1085,1355240265),(529878,1085,1355237320),(529947,1045,1357934785),(529947,1085,1355240037),(529974,1046,1357142405),(530456,1045,1355265586),(530456,1085,1355265382),(530728,1046,1357129405),(531187,1085,1355238880),(531234,1085,1355244348),(531310,1085,1355236706),(531449,1236,1357247709),(531679,1085,1355251982),(531883,1045,1356143339),(531957,1045,1357917329),(532056,1085,1355243065),(532086,1085,1355242890),(532110,1045,1355514183),(532110,1227,1355514180),(532183,1085,1355237106),(532626,1045,1357087727),(532730,1085,1355242901),(532842,1085,1355245624),(533747,1046,1357337175),(534470,1045,1357751607),(534913,1045,1357390097),(534914,1085,1355341817),(534948,1085,1355247041),(535389,1045,1357934392),(535643,1236,1357082370),(535811,1085,1355318075),(536066,1085,1355228639),(536111,1045,1357438716),(536303,1046,1357324763),(536384,1045,1357359982),(536464,1085,1355237917),(536492,1045,1357660176),(536820,1045,1357933694),(537020,1045,1357245291),(537126,1085,1355244854),(537600,1085,1355248564),(537767,1045,1357582749),(537988,1085,1355239183),(537988,1236,1355239345),(538337,1045,1357244960),(539007,1045,1357348166),(539007,1085,1355256713),(539101,1045,1357934052),(539235,1085,1355238128),(539394,1045,1357945136),(539623,1236,1356132668),(539778,1045,1357946990),(539888,1085,1355243575),(540341,1085,1355428826),(540359,1045,1355771141),(540870,1045,1355832623),(540880,1045,1357352980),(540880,1046,1356436275),(540880,15080,1355939167),(540995,1045,1356721421),(541091,1045,1355871409),(541157,11945,1357939673),(541491,1085,1355260445),(541510,1085,1355250430),(542987,1045,1357932038),(543134,1236,1357334713),(543164,1236,1357144129),(543216,1085,1355186696),(543544,1045,1357823022),(543689,1045,1355270500),(543825,1045,1358027712),(544017,1236,1357529905),(544045,1045,1357671146),(544116,1045,1355273071),(544238,1045,1356188793),(545410,1085,1355244752),(545873,1085,1355255373),(546033,1045,1355946006),(546126,1085,1355319515),(546586,1045,1355819606),(546632,1045,1357958689),(546669,1045,1357077338),(546706,1045,1357324442),(546717,1045,1357335661),(546717,1046,1357335589),(546977,1045,1357947115),(547195,1085,1355287325),(547225,1046,1357340219),(547225,1085,1355262234),(547434,1085,1355177140),(547646,1046,1355840549),(547675,1085,1355236176),(547761,1045,1357389319),(547796,1045,1355830409),(547796,1046,1357337623),(547884,1085,1355286393),(547897,1045,1356232608),(548212,1045,1357937903),(548316,1045,1357353267),(548349,1046,1357326796),(548349,1236,1357326851),(548399,1045,1357395765),(548562,1045,1355507923),(548802,1085,1355312260),(548808,1045,1357353865),(549182,1046,1356055941),(549346,1042,1357337707),(549346,1046,1357337708),(550153,1045,1356296530),(550411,1045,1357959506),(550780,1045,1357934752),(551349,1046,1355175858),(551634,1045,1357956810),(552439,1236,1357331283),(553148,1046,1357336983),(553329,1085,1355499676),(553426,1045,1355919605),(553623,1040,1357337774),(553623,1045,1357337774),(553623,1046,1357337726),(553934,1046,1357264006),(554170,1045,1357335590),(554810,1045,1355862370),(555151,1046,1356152103),(555164,1085,1355236600),(555574,1236,1358140383),(555699,1085,1355329336),(555781,1045,1357151149),(556058,1085,1355285046),(556078,1045,1355547641),(556120,1045,1357365164),(556392,1045,1357933909),(556392,1085,1355247866),(556533,1045,1356198091),(556720,1045,1355243699),(556720,1085,1355243687),(556748,1045,1357800078),(556992,1085,1355235546),(557073,1045,1357075527),(557167,1085,1355246200),(557561,1045,1357245601),(557599,1045,1357345497),(557678,1046,1357338230),(558128,1045,1357935599),(558129,1045,1356743405),(558438,1085,1355412469),(558447,1045,1358130149),(558447,1236,1355343744),(558452,1045,1358008379),(558625,1045,1357335628),(558630,1045,1357610046),(558695,1045,1357335599),(558757,1045,1357084181),(558949,1046,1357339120),(559361,1045,1358123577),(559568,1045,1357945206),(559667,1045,1357316734),(560079,1046,1357340577),(560082,1085,1355239733),(560247,1236,1357856975),(560316,1085,1355279649),(560536,1085,1355267210),(560814,1085,1355237110),(560824,1045,1357971780),(561146,1046,1357254207),(561148,1045,1355838793),(561781,1045,1357246977),(561781,1046,1357340558),(562040,1045,1357356718),(563043,1046,1356101045),(563188,1236,1357261344),(563670,1045,1357075896),(563768,1045,1355627092),(563768,1227,1355627091),(563768,1236,1355627070),(564026,1045,1357352422),(564215,1085,1355237648),(564215,1236,1355237811),(564369,1046,1357340038),(564598,1045,1357936296),(564658,1085,1355252397),(565343,1045,1357360219),(565403,1046,1357341114),(565564,1045,1357082908),(565573,1045,1357938835),(565892,1045,1357746480),(565892,1046,1355176284),(566001,1046,1357336361),(566072,1085,1355241804),(566668,1045,1357353391),(566707,1045,1357765515),(567057,1045,1355248801),(567057,1085,1355383263),(567400,1046,1357336464),(567550,1045,1357356624),(567640,1046,1357338827),(567652,1045,1357933257),(567681,1046,1357337810),(567694,1045,1357694361),(567707,1045,1357348254),(567730,1045,1357659851),(568087,1045,1357778638),(568090,1045,1358074569),(568090,1046,1357210512),(568149,1085,1355242325),(568149,1236,1355242275),(568162,1045,1357955441),(568425,1045,1357600235),(568425,1085,1355240291),(568518,1045,1357328001),(569027,1045,1355928057),(569027,1227,1355928053),(569451,1045,1355842039),(569458,1045,1355823388),(569840,1045,1357363438),(569986,1045,1358040323),(569986,1085,1355278771),(570612,1045,1357529624),(570624,1045,1357359231),(570626,1085,1355284027),(570634,1046,1357340348),(570737,1045,1357368223),(570737,1227,1357368223),(570737,11937,1357291868),(570737,14961,1357225616),(570737,15020,1355559615),(570737,15047,1355559726),(570737,15066,1355559666),(570737,15086,1357225546),(570737,15097,1357291762),(570737,15107,1357807216),(570737,15110,1358136061),(571157,1236,1357326876),(571174,1045,1357976298),(571380,1085,1355238590),(571647,1085,1355279562),(571647,1236,1355811416),(571884,1045,1355821455),(571931,1045,1357669925),(571946,1045,1358140088),(571956,1046,1357333797),(572042,1046,1357338219),(572094,1085,1355264417),(572490,1045,1357366063),(572517,1045,1357947385),(573040,1085,1355254032),(573124,1046,1357340603),(573240,1045,1357948983),(573410,1046,1357340459),(573529,1046,1355813557),(573571,1045,1357767959),(573847,1046,1357340898),(573958,1045,1357932864),(574126,1045,1355845867),(574518,1045,1357614549),(575139,1085,1355236246),(575489,1236,1357613351),(575628,1045,1357753169),(575675,1045,1357630168),(575675,1227,1357630150),(575748,1045,1357090014),(575781,1045,1357257802),(575837,1045,1357352562),(575837,1085,1355270198),(575926,1045,1358099272),(576101,1045,1357911951),(576173,1045,1355888348),(576270,1085,1355243027),(576797,1046,1357338750),(576844,1046,1355783263),(576850,1045,1357323894),(576911,1085,1355255397),(577080,1085,1355243691),(577142,1045,1355506776),(577410,1045,1357347811),(577842,1046,1355834953),(578011,15091,1356402295),(578276,1085,1355244081),(578490,1045,1357253451),(578848,1085,1355254342),(579101,1045,1357353001),(579101,11952,1357950154),(579154,1046,1357324108),(579866,1045,1357343783),(579866,1227,1357343781),(579866,1236,1357343912),(580047,1046,1357338059),(580167,1045,1357936700),(580457,1045,1357248947),(580681,1045,1357346899),(580955,1045,1357364833),(581343,1045,1356138173),(581578,1045,1357948556),(581662,1085,1355241127),(581748,1046,1357340204),(582041,1046,1356216698),(582374,1045,1357264737),(582608,1045,1357975249),(582870,1085,1355247161),(583081,1046,1357246283),(583863,1045,1357335298),(583893,1045,1357832756),(583896,1045,1357685929),(584056,1046,1357340047),(584250,1046,1357662389),(584609,1045,1357357281),(584622,1045,1355541866),(584622,1085,1355250938),(585186,1045,1356129503),(585264,1045,1358015378),(585416,1236,1355846841),(585583,1085,1355242729),(585636,1045,1357947668),(585922,1046,1357338164),(585995,1046,1357179094),(585995,1236,1357151036),(586001,1045,1355176031),(586265,1085,1355238666),(586345,1045,1357350953),(586345,1227,1357350952),(586787,1045,1357685735),(588017,1085,1355246050),(588241,1045,1357686259),(588511,1045,1357327659),(588511,1046,1357249335),(588752,1045,1356308007),(588970,1085,1355275401),(588970,1236,1355189807),(590297,1045,1357372703),(590456,1227,1357102430),(590456,1236,1357102390),(590573,1045,1357779788),(590960,1045,1357330453),(591171,1046,1357340206),(591890,1046,1356813926),(592320,1046,1357339342),(592393,1045,1357767558),(592621,1085,1355244490),(592751,1045,1355543743),(592751,1085,1355247948),(593285,1046,1357760154),(593424,1085,1355259296),(593595,1045,1358150449),(593714,1085,1355225326),(593841,1046,1355843955),(593848,1045,1357780830),(594100,1046,1355402079),(595004,1085,1355243933),(595004,1236,1357387614),(595135,1046,1357334332),(595326,1085,1355238606),(595403,1085,1355240265),(595752,1045,1357304213),(596017,1045,1357944865),(596066,1046,1357168952),(596080,1046,1357337709),(596298,1046,1357178323),(596454,1045,1357587773),(596454,1046,1357243699),(596545,1045,1357348152),(596561,1045,1356184807),(596703,1045,1357087858),(597194,1045,1355872139),(597351,1085,1355241097),(597373,1045,1357698521),(597373,1227,1357698520),(597373,1236,1357698632),(597753,1045,1357780991),(597753,1227,1357780988),(598069,1045,1356120912),(598260,1045,1357357015),(598777,1045,1357366803),(598973,1085,1355246775),(599983,1045,1357384427),(600206,1045,1357306346),(600383,1045,1357342346),(600383,1085,1355235696),(600419,1045,1357932898),(600498,1045,1357418372),(600539,1045,1357359417),(600576,1045,1355274127),(600630,1045,1357365978),(600943,1046,1355176329),(600947,1045,1357936922),(601150,1045,1357586689),(601382,1045,1356150787),(601382,1085,1355240622),(603462,1046,1355841308),(603595,1045,1357352544),(604189,1085,1355256987),(604297,1085,1355286380),(604376,1045,1357950215),(604555,1045,1358007888),(604783,1045,1357330058),(604843,1085,1355241608),(604843,1236,1355241857),(604918,1236,1357492403),(605050,1045,1357335537),(605137,1236,1357363809),(605393,1045,1357950542),(605565,1085,1355441831),(606122,1046,1356501517),(606330,1045,1357502967),(606654,1085,1355236684),(606997,1045,1358123456),(607386,16,1357245523),(607386,1046,1357245478),(608799,1045,1357938016),(608799,1046,1357336281),(609148,1045,1357114001),(610046,1045,1357844370),(610082,1045,1358019508),(610123,1085,1355242356),(610268,1236,1357404537),(610957,1046,1357560867),(611109,1046,1355837621),(611338,1045,1357594155),(611338,15085,1356041736),(611396,1045,1357949575),(611725,1045,1355928806),(611746,1046,1355851120),(611794,1045,1357190245),(612417,1085,1355261415),(612899,1045,1357253929),(613069,1085,1355235279),(613275,1045,1357078208),(613948,1045,1355808310),(614760,1045,1357615097),(614974,1085,1355341054),(615472,1045,1357752124),(616996,1045,1357182710),(617197,1046,1357329654),(617209,1046,1357254476),(617229,1085,1355441840),(617299,1045,1357250993),(617928,1046,1357326817),(617941,1045,1355558846),(617941,1227,1355558843),(617960,1045,1357446345),(618052,1045,1357330426),(618193,1045,1357692161),(618903,1085,1355252189),(620694,1045,1357778578),(621089,1085,1355269334),(622248,1046,1357337389),(622442,1045,1358014838),(622698,1085,1355256028),(623107,1045,1355839203),(623375,1045,1357353015),(623412,1045,1357373385),(624374,1045,1357329832),(624701,1045,1357347881),(624701,1085,1355236604),(624845,1045,1357075664),(627136,1085,1355235926),(627259,1045,1357353473),(627475,1085,1355244793),(627914,1045,1355841123),(628236,1085,1355246868),(628319,1085,1355243221),(628338,1236,1357324842),(628504,1085,1355242477),(628629,1085,1355237488),(628654,1046,1357333657),(628769,1085,1355238594),(628775,1045,1357244495),(628825,1045,1357082490),(628981,1045,1357249326),(629084,1045,1356147821),(629098,1085,1355273418),(629134,1085,1355240617),(629175,1045,1355913460),(629296,1085,1355286008),(629304,1085,1355241893),(629470,1045,1357374539),(629470,1085,1355265935),(629484,1085,1355249660),(630255,1045,1357938531),(630255,1085,1355242390),(630297,1085,1355238785),(630437,1045,1355245575),(630444,1046,1357361429),(630444,1085,1355291538),(630593,1045,1357496782),(630623,1045,1357935825),(630786,1085,1355270556),(630933,1085,1355237462),(631054,1045,1357066129),(631054,1046,1358125265),(631054,1227,1357066128),(631127,1045,1357767522),(631550,1085,1355241655),(631567,1045,1355515172),(632985,1236,1357608814),(633045,1085,1355284510),(633117,1085,1355253995),(633767,1045,1357942764),(635973,1045,1358110339),(636338,1045,1357778456),(636527,1236,1357090642),(636532,1045,1357885751),(636532,1046,1357340085),(636564,1085,1355250685),(636854,1045,1357942666),(636854,1227,1355845980),(636899,1085,1355288838),(636931,1085,1355324401),(637075,1045,1357385825),(637435,1045,1357971066),(637766,1045,1355508798),(637837,1045,1357245575),(637959,1045,1355601883),(638364,1085,1355367549),(638396,1045,1357253286),(638551,1085,1355325664),(638645,1045,1357869271),(638660,1085,1355253208),(639266,1045,1357389535),(639466,1045,1358028261),(639466,1227,1358028260),(639514,1045,1357375941),(639514,1236,1357247253),(639535,1045,1357596724),(639535,1046,1357256654),(639652,1045,1355807286),(639762,1045,1357327841),(639762,1227,1357327807),(639762,1236,1357327843),(639861,1045,1355877584),(639929,1045,1357933629),(640025,1045,1358029568),(640085,1045,1355263616),(640299,1045,1357849588),(640385,1045,1358111406),(640615,1045,1357320239),(640615,1085,1355433379),(640659,1045,1357327480),(641031,1045,1357940828),(641577,1085,1355239738),(642262,1045,1356178164),(642262,1046,1357254245),(642392,1045,1357933140),(642909,1045,1357779095),(643012,1045,1357372331),(643337,1046,1357336467),(643513,1045,1357335130),(643513,1046,1357335132),(643631,1085,1355239094),(643779,1046,1357340392),(643877,1045,1357742685),(643927,1085,1355253284),(644089,1045,1355886578),(644205,1045,1357869440),(644326,1045,1355808326),(644326,1227,1355808322),(644542,1085,1355239942),(644629,1085,1355240984),(644668,1085,1355237695),(644690,1046,1357341188),(644931,1045,1358016606),(644931,1236,1358016566),(645012,1045,1356639270),(645258,1085,1355380625),(645362,1085,1355282910),(645460,1046,1355176340),(645463,1085,1355331469),(645530,1045,1357090780),(645640,1046,1357339918),(645879,1045,1357969508),(645894,1085,1355249173),(645910,1046,1356890522),(645946,1046,1356010777),(645974,1045,1357668304),(645974,13278,1357434772),(645996,1045,1357246133),(646019,1085,1355381319),(646036,1046,1356829692),(646139,1236,1355418939),(646167,1045,1357943670),(646535,1046,1357945549),(646543,1046,1356344914),(646543,1085,1355303739),(646598,1085,1355241016),(646685,1045,1357932941),(646779,1085,1355237323),(647072,1045,1358130074),(647086,1085,1355248239),(647124,1085,1355265851),(647203,1046,1357338850),(647327,1045,1357358024),(647416,1046,1357337337),(647629,1046,1357004367),(647766,1046,1357336219),(647854,1045,1356399834),(648055,1040,1357337439),(648055,1042,1357337399),(648055,1045,1357337439),(648055,1046,1357337447),(648205,1045,1357949411),(648205,1046,1357339797),(648205,1085,1355273848),(648206,1045,1355346738),(648206,1227,1355346735),(648351,1085,1355241738),(648362,1045,1357422276),(648486,1085,1355272805),(648534,1085,1355251353),(648622,1085,1355238495),(649428,1045,1355882229),(649472,1045,1357987662),(649522,1085,1355270948),(649628,1045,1355506521),(649664,1085,1355237783),(649855,1046,1357338661),(649913,1045,1356491092),(649964,1046,1355824913),(650830,1045,1357760711),(650963,1045,1358140897),(650968,1085,1355275909),(651249,1046,1357604260),(651344,1085,1355238932),(651648,1085,1355177890),(651928,1085,1355270263),(652068,1085,1355237239),(652111,1085,1355246358),(652128,1236,1355214050),(652408,1085,1355288523),(652665,1046,1357327174),(652665,1085,1355293425),(652940,1085,1355236952),(653043,1045,1357613847),(653331,1046,1355855557),(653437,1045,1357372268),(653476,1045,1357256362),(653514,1045,1357435463),(653607,1045,1357398727),(653690,1045,1358123823),(653690,1046,1357337993),(653851,1045,1357945894),(654066,1046,1357337625),(654136,1085,1355235942),(654315,1045,1355891803),(654677,1236,1357933781),(654800,1085,1355241484),(655004,1045,1358011244),(655102,1045,1357271188),(655264,1045,1357622752),(655264,1227,1357622750),(655277,1085,1355355715),(655432,1085,1355283824),(655440,1046,1357339093),(655472,1085,1355460439),(655473,1085,1355258269),(655490,1046,1357324742),(655490,1236,1357324937),(655587,1045,1357948111),(655587,1085,1355338355),(655587,1236,1357142768),(655618,1045,1357948023),(655630,1045,1357400160),(655641,1045,1357956913),(655670,1045,1357947532),(655685,1236,1357086543),(655728,1045,1357612443),(655934,1085,1355236253),(655940,1046,1357338477),(655956,1046,1355847934),(656176,1085,1355245008),(656219,1085,1355256550),(656483,1045,1356130761),(656644,1085,1355373253),(656834,1045,1357971160),(656837,1085,1355331209),(656839,1085,1355240213),(656858,1042,1357939264),(656858,1045,1357939267),(656929,1085,1355276487),(657040,1045,1357289490),(657079,1045,1356122654),(657321,1045,1357735178),(657624,1085,1355286752),(657650,1085,1355330559),(657734,1045,1355861485),(657926,1085,1355285770),(658066,1045,1357953935),(658167,1045,1357441672),(658167,1227,1357441669),(658219,1046,1355860811),(658321,1045,1357353702),(658381,1045,1358138137),(658540,1085,1355240792),(658550,1085,1355254135),(658556,1085,1355243325),(658667,1046,1357339504),(658676,1046,1357661699),(658837,1045,1355832620),(658950,1085,1355244155),(659031,1045,1355843986),(659552,1046,1357337083),(659694,1085,1355244060),(659845,1085,1355264885),(660228,1046,1357280807),(660293,1045,1357370713),(660298,1085,1355176708),(660349,1045,1356122385),(660809,1085,1355247711),(660819,1045,1357933478),(660970,1046,1355810726),(661023,1085,1355369512),(661062,1085,1355243588),(661080,1085,1355193615),(661178,1085,1355259188),(661283,1085,1355236335),(661361,1085,1355256450),(661433,1046,1355808341),(661444,1046,1357337025),(661444,1085,1355240510),(661541,1045,1357397952),(661541,1046,1356298860),(662155,1085,1355364618),(662226,1045,1355810038),(662242,1045,1357347265),(662564,1085,1355237320),(662786,1236,1355257483),(662903,1045,1357497040),(663042,1085,1355277022),(663308,1045,1357335789),(663308,1085,1355240437),(663633,1045,1357364316),(663664,1085,1355242341),(663835,1045,1356129025),(663868,1085,1355244279),(663879,1040,1355812162),(663879,1045,1355812166),(664710,1045,1357941376),(664823,1045,1357345027),(664933,1085,1355268941),(665054,1045,1357352819),(665488,1046,1356749972),(665616,1046,1355727507),(665687,1046,1357339629),(665722,1045,1357244991),(665888,1045,1355862534),(665926,1085,1355237023),(666016,1085,1355237058),(666072,1085,1355176448),(666079,1085,1355327111),(666174,1085,1355238381),(666243,1045,1357882870),(666367,1045,1357361721),(666378,1045,1357691915),(666422,1085,1355367882),(666468,1045,1358038783),(666969,1046,1355834832),(667056,1085,1355236499),(667255,1045,1356124586),(667455,1045,1357518440),(667693,1085,1355235384),(667772,1045,1355840648),(667772,1085,1355256366),(667815,1045,1357385625),(668128,1045,1357359484),(668260,1085,1355201603),(668627,1085,1355243673),(668734,1085,1355237140),(668853,1046,1355838979),(668923,1046,1355852859),(668967,1085,1355236819),(668981,1045,1357073712),(669024,1045,1358003808),(669037,1085,1355275233),(669188,1046,1357326855),(669361,1085,1355238581),(669381,1045,1357585725),(669450,1045,1357601960),(669477,1085,1355175837),(669510,1085,1355236655),(669641,1085,1355449382),(669754,1045,1356140931),(669819,1085,1355240153),(669930,1045,1356126926),(669939,1046,1355809866),(670030,1045,1357399559),(670030,1085,1355239088),(670132,1045,1357678542),(670135,1045,1358084758),(670135,1046,1357910719),(670167,1046,1357258378),(670176,1085,1355237787),(670251,1045,1357941472),(670342,1045,1357347383),(670342,1236,1357936452),(670535,1045,1357425435),(670535,1085,1355254571),(670600,1045,1358016853),(670698,1045,1357158182),(670787,1045,1357353469),(670870,1045,1355185661),(670900,1046,1355810012),(671080,1085,1355263592),(671375,1085,1355237805),(671387,1045,1355849886),(672082,1045,1357247863),(672236,1236,1357266720),(672239,1085,1355245578),(672903,1046,1357339193),(673087,1085,1355240178),(673209,1085,1355235870),(673376,1045,1357934473),(673577,1045,1357114638),(673577,1046,1356422598),(673747,1046,1357768641),(673749,1045,1356232746),(673775,1085,1355258738),(673795,1045,1357951021),(674382,1045,1355881067),(674382,1227,1355881064),(674773,1085,1355235410),(675049,1045,1357390119),(675061,1045,1357262562),(675182,1085,1355245964),(675246,1045,1356180976),(675928,1085,1355237106),(676194,1045,1357938144),(676332,1085,1355253714),(676437,1045,1357327858),(676437,1046,1357337388),(676667,1045,1357933861),(676667,1046,1357326899),(677365,1045,1357270726),(677470,1045,1357755642),(677470,1236,1355935783),(677641,1045,1358044340),(677874,1045,1356123562),(677920,1045,1355853754),(678062,1045,1357324059),(678062,1046,1357324083),(678285,1045,1357626091),(678511,1046,1355829573),(678528,1045,1357316445),(678660,1046,1355855319),(678713,1046,1355811910),(678725,1236,1355188457),(678771,1045,1357245740),(678771,1046,1357245493),(678918,1045,1357943925),(678931,1085,1355249000),(679058,1085,1355253038),(679090,1085,1355247357),(679094,1085,1355235517),(679120,1045,1357253226),(679143,1045,1358012992),(679415,1085,1355262254),(679794,1045,1355531013),(679953,1045,1357957989),(680143,1046,1355864889),(680308,1045,1357389577),(680592,1085,1355238355),(680628,1045,1357932039),(680657,1045,1358024619),(680771,1085,1355249927),(680796,1085,1355280651),(680823,1085,1355247605),(681029,1045,1357965417),(681131,1046,1355887317),(681654,1085,1355241645),(681816,1045,1356148125),(681909,1045,1357945434),(682321,1045,1356130450),(682469,1045,1357958666),(682488,1085,1355276731),(682626,1045,1357348029),(682936,1045,1357323977),(683038,1045,1355517665),(683188,1046,1357324106),(683562,1045,1357957237),(683594,1085,1355238235),(683632,1085,1355280928),(683759,1045,1357510483),(683799,1045,1357347580),(683901,1085,1355240973),(683935,1046,1357934472),(684041,1085,1355256619),(684150,1045,1357117424),(684150,1227,1357117421),(684160,1045,1357365852),(684192,1045,1357935565),(684192,1046,1357336408),(684269,1085,1355255450),(684314,1045,1357676803),(684323,1045,1355867172),(684425,1045,1357871510),(684447,1085,1355247433),(684480,1085,1355318557),(684505,1085,1355320954),(684732,1085,1355265053),(684999,1045,1357324466),(685158,1045,1357096421),(685440,1045,1357327658),(685486,1045,1357248905),(685661,1045,1356068827),(686310,1046,1355841546),(686312,1085,1355235449),(686554,1085,1355254444),(686653,1085,1355236719),(686660,1045,1355841999),(686908,1045,1356144424),(686942,1040,1357339584),(686942,1045,1357339584),(686942,1046,1357339916),(687099,1046,1355831046),(687144,1085,1355287083),(687390,1085,1355339296),(687715,1046,1357663053),(687821,1085,1355239362),(687880,1045,1357341112),(687880,1046,1357340646),(688026,1085,1355236958),(688295,1046,1358146892),(688349,1045,1357379296),(688566,15078,1355855053),(688644,1085,1355237645),(688783,1045,1355841078),(689052,1046,1357341440),(689097,1045,1355504901),(689312,1085,1355254597),(689787,1085,1355319883),(689972,1045,1357676048),(690009,1046,1355874164),(690111,1046,1355842094),(690858,1236,1355268442),(690951,1085,1355256411),(691037,1085,1355505641),(691264,1046,1356462881),(691578,1045,1358142856),(691578,1227,1357522595),(691595,1046,1357339955),(691710,1045,1357777378),(691772,1045,1357245032),(691919,1045,1355847961),(692039,1045,1357226786),(692186,1045,1357308520),(692388,1045,1357100909),(692541,1045,1357631654),(692586,1045,1357693584),(692724,1085,1355236428),(693142,1085,1355323808),(693400,1040,1355260512),(693400,1045,1355260526),(693414,1085,1355301211),(693502,1085,1355257927),(693542,1085,1355288833),(693612,1045,1357327942),(694014,1046,1357255802),(694232,1085,1355248150),(694308,1085,1355236285),(694312,1085,1355241046),(694333,1085,1355236827),(694378,1085,1355277803),(694530,1045,1357878300),(694530,1046,1355836026),(694542,1045,1357250561),(694823,1045,1357750666),(694927,1085,1355244455),(695087,1085,1355236968),(695163,1085,1355253611),(695209,1085,1355237183),(695259,1042,1357341528),(695259,1046,1357341529),(695530,1085,1355244398),(695615,1236,1357135816),(695619,1045,1355832146),(696040,1045,1357962090),(696393,1045,1357621221),(696499,1046,1355959837),(696567,1046,1357326897),(696614,1045,1357340692),(696614,1046,1357340691),(697246,1085,1355239261),(697357,1045,1358045349),(697544,1085,1355248198),(698308,1085,1355362310),(698387,1045,1357951318),(698474,1045,1357759776),(698787,1085,1355356084),(699464,1045,1355831899),(699834,1045,1357359110),(700535,1085,1355279896),(700971,1085,1355244886),(701112,1045,1357596644),(701283,1045,1357364287),(701283,11950,1357960709),(701542,1045,1355302547),(701542,1085,1355302561),(702248,1085,1355243627),(702481,1045,1356130431),(703245,1085,1355270682),(703255,1046,1357337143),(703289,1045,1357947532),(703413,1085,1355271894),(703417,1042,1357940571),(703417,1045,1357940572),(703489,1085,1355294307),(703501,1045,1357523721),(703673,1045,1357402046),(703948,1045,1355851483),(704014,1045,1357663315),(704159,1236,1355873556),(704211,1085,1355342335),(704289,1045,1357253103),(704303,1045,1355816855),(704347,1045,1357973840),(704515,1045,1358020455),(704944,1046,1357900759),(704960,1085,1355237544),(705113,1045,1358009225),(705338,1045,1355841393),(705347,1085,1355190302),(707636,1085,1355249474),(707703,1085,1355326414),(707853,1045,1357581665),(708229,1045,1355634400),(708229,1046,1355384678),(708229,1236,1355460412),(708525,1045,1357769604),(708591,1085,1355425362),(708768,1045,1357328014),(709067,1045,1357963661),(709563,1085,1355263521),(709731,1236,1356218547),(709777,1045,1357144189),(709780,1046,1358109491),(709798,1045,1358004689),(710019,1085,1355299878),(710139,1085,1355252257),(710314,1046,1357080618),(710531,1085,1355242286),(710567,1045,1357950273),(710650,1085,1355246370),(710909,1045,1357323989),(710909,1046,1357324165),(711204,1045,1357943343),(711204,1085,1355241081),(711204,1236,1355241102),(711613,1045,1357361810),(711736,1085,1355251466),(711796,1045,1357590566),(712046,1085,1356188091),(712091,1045,1355807522),(712267,1045,1357931752),(712389,1045,1356130433),(712389,1085,1355239165),(712492,1085,1355175858),(712784,1236,1355846317),(712872,1045,1357864915),(713679,1046,1356714854),(713705,1045,1357604021),(713935,1046,1357335871),(714099,1046,1357254404),(714099,1085,1355333718),(714163,1085,1355238501),(714441,1045,1357328022),(714441,1236,1357329429),(714684,1045,1357829695),(714684,1085,1355244167),(714713,1045,1357328002),(714806,1045,1358043732),(715144,1045,1357965361),(715260,1045,1357376415),(715685,1085,1355243568),(715794,1045,1355368252),(716135,1045,1355840324),(716135,1046,1357336299),(716586,1085,1355200389),(717208,1045,1357602333),(717645,1045,1357335529),(717789,1045,1357599504),(718227,1046,1356358825),(718273,1085,1355240323),(718400,1236,1357475898),(718697,1046,1357244575),(718974,1045,1357807817),(718974,1046,1357807273),(719118,1045,1357347809),(719158,1045,1357952580),(719267,1085,1355328759),(719295,1085,1355419002),(719356,1085,1355252059),(719428,1085,1355238225),(719669,1045,1356037856),(719745,1045,1355505265),(719841,1045,1357335471),(720149,1085,1355249698),(720324,1045,1356122709),(720617,1046,1355914749),(720660,1085,1355389294),(720721,1045,1355282596),(721043,1046,1357075998),(721044,1085,1355241040),(721322,1085,1355249119),(721583,1045,1358129826),(721583,1236,1355453930),(721914,1045,1357373704),(721981,1042,1357338570),(721981,1046,1357338572),(722292,1045,1357328022),(722638,1045,1356124365),(722638,1046,1355852323),(722655,1236,1357297803),(722840,1045,1357327877),(722894,1085,1355237193),(722917,1085,1355236561),(722955,1045,1357962131),(723172,1045,1357606376),(723235,1045,1357431900),(723397,1085,1355243690),(723440,1045,1355176984),(723636,1045,1355831092),(723811,1085,1355238201),(724956,1085,1355255447),(725603,1085,1355262322),(725604,1046,1357433036),(725659,1046,1357942933),(725952,1085,1355281902),(726074,1045,1357094436),(726151,1046,1356017443),(726209,1045,1355848251),(726264,1085,1355266915),(726340,1046,1355933649),(726609,1045,1357593465),(726731,1085,1355277376),(726741,1046,1355853377),(726927,1046,1355758783),(726950,1045,1358140402),(727544,1045,1357954227),(727886,1236,1357283803),(728218,1045,1355279034),(728231,1046,1355847353),(728239,1045,1357359012),(728264,1045,1355858507),(728372,1046,1355840838),(728507,1045,1357931404),(728530,1045,1357934279),(728583,1046,1357339456),(729022,1045,1356202841),(729214,1045,1355853047),(729241,1046,1357326898),(729397,1085,1355278717),(729825,1045,1357327946),(730058,1085,1355236479),(730150,1046,1356246174),(730150,1085,1355239547),(730270,1045,1357324588),(730274,1045,1355272765),(730274,1085,1355272780),(730508,1045,1357959126),(730666,1046,1357933975),(730689,1045,1357359058),(730887,1085,1355237841),(730973,1085,1355239365),(731004,1085,1355271038),(731026,1085,1355245811),(731141,1085,1355246896),(731770,1046,1355807977),(731923,1046,1356336042),(732738,1085,1355242363),(732851,1085,1355268546),(733104,1045,1357968638),(733114,1085,1355249823),(733188,1085,1355279673),(733228,1046,1355835177),(733498,1085,1355264753),(733642,1085,1355244355),(733657,1046,1357339469),(734008,1045,1357593908),(734267,1046,1355970503),(734583,1045,1355845514),(734583,1085,1355238207),(734617,1085,1355248993),(734694,1085,1355264134),(734848,1045,1355831125),(734876,1085,1355236590),(735046,1045,1355983864),(735513,1045,1357014247),(735532,1045,1357669886),(735770,1045,1355845315),(736219,1085,1355240778),(736231,1046,1355883401),(736305,1085,1355252193),(736465,1046,1355851063),(736568,1046,1355844293),(736657,1085,1355256349),(737167,1236,1357761788),(737212,1046,1357340988),(737325,1085,1355236375),(737639,1085,1355366011),(737667,1085,1355315033),(737787,1085,1357530880),(737918,1085,1355276701),(738041,1045,1358008295),(738041,1085,1355249844),(738136,1085,1355250085),(738168,1085,1355245926),(738283,1046,1355816005),(738605,1045,1357402051),(738709,1045,1358002131),(738881,1046,1355806372),(738892,1045,1357959138),(738967,1085,1355247103),(739067,1045,1357970164),(739067,1046,1355877007),(739415,14,1357583603),(739415,305,1357579210),(739415,1045,1357675480),(739415,1046,1357845699),(739415,13255,1357579223),(739415,15097,1357575023),(739651,250,1355436991),(739651,1045,1357916168),(739651,1046,1357930591),(739651,2260,1355176588),(739651,12305,1355346543),(739651,15076,1355774387),(739651,15097,1357311144),(739651,15108,1357767971),(739702,1045,1357326686),(739702,1227,1357326684),(739772,1045,1357332468),(739772,1046,1357077341),(739838,1045,1357381920),(740284,1046,1355847588),(740756,1045,1357335435),(740756,1085,1355237280),(741263,1046,1357336429),(741290,1045,1357860662),(741303,1085,1355240234),(741368,1045,1357945858),(741368,1085,1355442909),(741389,1085,1355283992),(741594,1085,1355263412),(742228,1045,1357255088),(742228,1085,1355259849),(742415,1045,1355876741),(742768,1085,1355243949),(742860,1046,1355808751),(743306,1236,1357086657),(743430,1085,1355281228),(743661,1045,1357359265),(743866,1085,1355250866),(743978,1085,1355237744),(744478,1045,1358027759),(744747,1045,1357247564),(744747,1085,1355243465),(744966,1045,1355874222),(744966,1046,1355874201),(745116,1085,1355262205),(745541,1085,1355375480),(745811,1045,1357930038),(745811,1227,1355511381),(745811,1236,1355511367),(746099,1045,1357347583),(746160,1045,1355508413),(746449,1046,1357326706),(746449,1085,1355240276),(746896,1045,1357932401),(746896,1046,1357338827),(746896,1085,1355256629),(747289,1085,1355176411),(747901,1045,1355821758),(748093,1085,1355236083),(748433,1045,1357365236),(748487,1046,1355828383),(748583,1045,1357934573),(748663,1085,1355269382),(748941,1045,1355839924),(749099,1085,1355239298),(749413,1085,1355349646),(749501,1046,1356895397),(749827,1085,1355253489),(750161,1046,1357341529),(750197,1085,1355249623),(750239,1045,1357353095),(750275,1085,1355236611),(750394,1085,1355248918),(750513,1046,1355864477),(750686,1085,1355430099),(750704,1045,1357950484),(750795,1046,1355976177),(750798,1046,1355839525),(751120,1046,1355977738),(751472,1085,1355349742),(751504,1045,1357792104),(751786,1085,1355468015),(751790,1085,1355371703),(752147,1045,1358041187),(752181,1085,1355236570),(752217,1085,1355241526),(752229,1085,1355280179),(752264,1045,1357938559),(752265,1046,1355815223),(752296,1085,1355236840),(752700,1085,1355244209),(752723,1085,1355245140),(752786,1045,1357359680),(752786,1085,1355244933),(752826,1045,1357329269),(752854,1045,1356554629),(752951,1045,1357684800),(752951,1046,1357336120),(753091,1042,1357337455),(753091,1046,1357337458),(753290,1085,1355277778),(753399,1045,1357661299),(753412,1085,1355242224),(753616,1045,1355238496),(753616,1085,1355238492),(753687,1045,1357366327),(753736,1046,1357337004),(753767,1045,1357245561),(753767,1227,1357245558),(754160,1045,1357624775),(754236,1045,1355515623),(754236,1085,1355237258),(754349,1085,1355312248),(754363,1045,1356147937),(754459,1046,1356576169),(754526,1046,1355837289),(754567,1045,1357424571),(754596,1085,1355285973),(755035,1046,1357336532),(755245,1045,1357245555),(755479,1045,1357337073),(755574,1046,1358005169),(755742,1085,1355273753),(755793,1085,1355243476),(755936,1045,1355528831),(755962,1045,1356729239),(756123,1085,1355244070),(756334,1045,1357401867),(756354,1045,1358103411),(756398,1045,1357609097),(756785,1085,1355239127),(756983,1046,1356389786),(757493,1085,1355255127),(757594,1085,1355275479),(757986,1085,1355255122),(758123,1045,1357943607),(758244,1085,1355256407),(758527,1085,1355346841),(758726,1045,1357781926),(758811,1085,1355197938),(758922,1085,1355237415),(759043,1040,1355970558),(759043,1045,1355970640),(759099,1045,1355348074),(759325,1045,1357359187),(759504,1085,1355261042),(759526,1045,1357939834),(759608,1045,1357370050),(759816,1045,1357784871),(759890,1046,1355838120),(760327,1046,1355824519),(760631,1046,1355845320),(760641,1045,1356122659),(760845,1085,1355236292),(760885,1045,1358037897),(761116,1045,1357328416),(761321,1045,1355522666),(761384,1045,1357334072),(761408,1045,1355512363),(761742,1045,1357350271),(761818,1085,1355251712),(761912,1085,1355238577),(761938,1085,1355287816),(762598,1046,1355869062),(762649,1046,1356199176),(762867,1046,1356071726),(762912,1045,1355541040),(762975,1045,1356154084),(762986,1085,1355262215),(763178,1046,1355875630),(763338,1085,1355275975),(763346,1085,1355278101),(763635,1045,1357963470),(763663,1046,1357328285),(763728,1046,1355935869),(763861,1085,1355240947),(763942,1045,1358099003),(763976,1085,1355338979),(763980,1085,1355250774),(763984,1045,1355835701),(764089,1045,1355180595),(764130,1085,1355250196),(764339,1045,1357353726),(764365,1046,1357326811),(764365,1085,1355236529),(764379,1045,1357101458),(764564,1085,1355332968),(764650,1046,1357337582),(764664,1085,1355271600),(764693,1085,1355239323),(764703,1085,1355240916),(764728,1045,1357353011),(764736,1046,1356676547),(764736,1085,1355383784),(764918,1045,1357760208),(764955,1085,1355427741),(764969,1085,1355236919),(765135,1046,1356671785),(765193,1046,1355846541),(765310,1045,1357336921),(765431,1045,1357347902),(765552,1085,1355244983),(765604,1085,1355251768),(765670,1045,1357084686),(765781,1046,1355837233),(766407,1045,1355587795),(766411,1045,1357073420),(766532,1045,1357953979),(766792,1085,1355317807),(766881,1045,1357343119),(767046,1045,1357269251),(767070,1085,1355252068),(767253,1085,1355203854),(767597,1045,1358046626),(767628,1085,1355241998),(767791,1045,1355518861),(767791,1085,1355290399),(767939,1085,1355245852),(767994,1045,1357379369),(768023,1046,1355828210),(768066,1046,1356067934),(768156,1045,1357994149),(768208,1085,1355262769),(768257,1045,1356137825),(768457,1045,1357329635),(768659,1045,1357932735),(768791,1045,1355769783),(768808,1046,1357330303),(768915,1045,1357399699),(768996,1085,1355269169),(769011,1085,1355237781),(769093,1046,1357325289),(769129,1045,1357347734),(769164,1085,1355242243),(769303,1045,1355605090),(769680,1045,1357403608),(769757,1045,1357409413),(769782,1046,1357326892),(770069,1046,1355885014),(770315,1046,1356030296),(770457,1085,1355268947),(770464,1045,1357358344),(770473,1046,1355948904),(770486,1085,1355368144),(770595,1045,1357401717),(770677,1085,1355247965),(770689,1046,1357475379),(770827,1045,1357962355),(770839,1046,1357327021),(771177,1045,1357763761),(771214,1045,1355529437),(771214,1085,1355444051),(771225,1045,1356121882),(771231,1236,1357335879),(771286,1045,1355824174),(771347,1045,1355859453),(771381,15094,1357419134),(771384,1040,1357339246),(771384,1045,1357339262),(771384,1046,1357339409),(771496,1085,1355238918),(771988,1085,1355238273),(772009,1045,1355526614),(772132,1046,1355896433),(772141,1046,1357254396),(772332,1042,1357339487),(772332,1046,1357340954),(772491,1085,1355801853),(772722,1085,1355238257),(772753,1085,1355234963),(772797,1045,1357955850),(772797,1046,1357338856),(772797,1085,1355336384),(773004,1085,1355270567),(773010,1045,1357510910),(773013,1046,1355823329),(773101,1046,1355838193),(773446,1085,1355238218),(773457,1046,1355849868),(773500,1085,1355242694),(773522,1045,1357401573),(773547,1045,1357932940),(773679,1046,1355719603),(773821,1045,1355509057),(774039,1045,1357402997),(774112,1085,1355247426),(774242,1046,1357340161),(774396,1085,1355186680),(774542,1085,1355361361),(774798,1045,1357345358),(774873,1045,1357928063),(774902,1085,1355240228),(774929,1045,1358051708),(775037,1045,1357358139),(775120,1045,1355259573),(775178,1085,1355334188),(775201,1085,1355178930),(775210,1046,1357336022),(775210,1085,1355282853),(775321,1085,1355359602),(775370,1085,1355393902),(775392,1045,1355843069),(775518,1045,1357097275),(775547,1046,1357839618),(775547,11950,1357933366),(775581,1085,1355238451),(775937,1085,1355243041),(776063,1085,1355241111),(776270,1085,1355256637),(776383,1046,1355859503),(776660,1046,1356573802),(776938,1045,1356139084),(776957,1085,1355242013),(776994,1085,1355269122),(777045,1046,1355859772),(777240,1045,1357358459),(777318,1085,1355236478),(777326,1046,1355809341),(777336,1085,1355345314),(777615,1085,1355262432),(777786,1085,1355236892),(777900,1045,1356480781),(778209,1085,1355235351),(778259,1045,1357938332),(778268,1085,1355239550),(779345,1046,1357338269),(779352,1046,1357339545),(779476,1045,1355541247),(779496,1085,1355351150),(779571,1046,1355835944),(779702,1085,1355236063),(779783,1046,1355507266),(779983,1045,1357388808),(780107,1085,1355294410),(780135,1045,1355809237),(780435,1045,1356125951),(780474,1046,1355834187),(780474,1085,1355314788),(780500,1085,1355252596),(780610,1045,1357954754),(780768,1085,1355239322),(780863,1045,1355527839),(781039,1045,1357956001),(781163,1046,1355861454),(781350,1045,1356976258),(781460,1085,1355239904),(781598,1085,1355240162),(781680,1085,1355250648),(781726,1085,1355359753),(781754,1045,1355681042),(781956,1045,1357530129),(782070,1045,1355732551),(782101,1085,1355246081),(782152,1085,1355248848),(782167,1046,1355849692),(782259,1085,1355261561),(782353,1046,1356824898),(782804,1045,1357349190),(782804,1227,1357349189),(782804,1236,1358106786),(782814,1085,1355422481),(782940,14,1355432869),(782940,1014,1355861404),(782940,1045,1357829190),(782940,5318,1355175122),(782940,11768,1357745961),(782940,11945,1355861433),(782940,15054,1355240504),(782940,15055,1355339789),(782940,15057,1355240476),(782940,15062,1355258544),(782940,15063,1355240431),(782940,15064,1355842249),(782940,15066,1355258476),(782940,15069,1355428606),(782940,15070,1355501638),(782940,15071,1355854413),(782940,15077,1355856786),(782940,15078,1355863236),(782940,15080,1355946696),(782940,15081,1355863301),(782940,15082,1355863395),(782940,15083,1356014195),(782940,15085,1356102294),(782940,15087,1356103734),(782940,15088,1356709990),(782940,15093,1357571563),(782940,15094,1357842905),(782940,15105,1357658322),(782940,15106,1357843488),(782940,15108,1357831117),(782940,15110,1357930264),(782940,15114,1357916899),(783551,1085,1355238704),(783691,1085,1355241651),(783805,1045,1357351635),(783823,1046,1355827547),(783853,1085,1355284101),(784087,1045,1357839511),(784186,1046,1355806975),(784292,1045,1357346977),(784301,1045,1356234415),(784370,1045,1356062297),(784515,1045,1355241943),(784515,1085,1355241959),(784628,1085,1355238229),(784707,1046,1355839005),(784728,1085,1355238402),(784813,1045,1357755300),(784872,1046,1355810093),(785074,1046,1356067558),(785119,1085,1355262395),(785250,1085,1355239295),(785264,1046,1355839937),(785393,1046,1355842507),(785415,1046,1355843643),(785475,1045,1357400616),(785527,1085,1355250951),(785596,1046,1355843150),(785853,1085,1355243625),(785882,1046,1355864556),(785954,1085,1355237011),(786143,1045,1357357465),(786175,1045,1358055924),(786218,1045,1357398806),(786218,1236,1357943626),(786254,1085,1355256501),(786347,1085,1355236736),(786452,1085,1355440307),(786470,1045,1356535479),(786494,1236,1357334209),(786767,1046,1355811341),(786863,1046,1355839353),(786876,1046,1357074184),(786890,1045,1357938859),(786890,1046,1357339924),(787011,1045,1355807829),(787011,1046,1355807775),(787046,1046,1357340494),(787213,1085,1355238200),(787235,1045,1356130488),(787306,1085,1355254830),(787339,1085,1355328910),(787376,1085,1355273574),(787425,1045,1357961686),(787454,1085,1355252812),(787484,1046,1355877381),(787520,1085,1355244073),(787661,1045,1357696597),(787661,1227,1357346295),(787716,1085,1355260689),(787798,1085,1355242374),(787842,1046,1355852115),(787892,1085,1355267448),(787940,1085,1355268770),(787968,1046,1355855357),(788063,1046,1355881766),(788104,1085,1355198885),(788114,1045,1355201680),(788162,1045,1358115748),(788266,1046,1355935609),(788326,1045,1358050196),(788355,1045,1357948871),(788412,1045,1356179437),(788460,1045,1355839381),(788484,1085,1355338688),(788506,1046,1355194159),(788544,1045,1358092580),(788544,1046,1358092572),(788565,1045,1357947789),(788602,1085,1355250826),(788621,1046,1355841793),(788621,1085,1355248734),(788635,1236,1355185566),(788699,1085,1355245497),(788808,1046,1357340258),(788970,1046,1355845995),(789016,1085,1355264653),(789228,1085,1355242209),(789262,1045,1355346191),(789297,1085,1355240138),(789557,1085,1355272194),(789561,1085,1355268365),(789573,1085,1355250210),(789619,1045,1356454134),(789626,1046,1357254864),(789738,1085,1355244081),(789748,1045,1356127687),(789921,1085,1355188379),(789996,1085,1355238114),(790045,1046,1357074100),(790106,1045,1357955429),(790221,1085,1355250732),(790344,1045,1357603538),(790442,1085,1355330346),(790575,1046,1355808753),(791008,1046,1355874585),(791080,1085,1355271144),(791470,1045,1357325673),(791474,1046,1355835041),(791720,1085,1355259125),(791801,1046,1357336746),(791858,1046,1357340108),(791909,1046,1356742141),(792002,1046,1355850751),(792061,1046,1355883404),(792062,1045,1357352678),(792179,1085,1355329417),(792264,1045,1357346546),(792264,1085,1355411930),(792370,1085,1355238013),(792562,1085,1355240141),(792753,1045,1355837871),(792753,1046,1355837856),(792788,1042,1357340584),(792788,1046,1357340662),(792864,1085,1355333735),(792898,1045,1357950656),(792922,1085,1355253994),(793011,1085,1355253753),(793483,1085,1355266189),(793547,1085,1355238016),(793582,1085,1355274032),(794047,1045,1356169221),(794047,1046,1355816714),(794254,1085,1355320190),(794367,1085,1355267279),(794384,1085,1355427244),(794563,1046,1355840420),(794722,1085,1355240760),(794745,1045,1355534829),(794816,1046,1355839480),(795139,1085,1355243296),(795357,1085,1355235380),(795381,1046,1357760293),(795393,1046,1355884294),(795618,1085,1355194487),(795754,1085,1355272116),(795807,1045,1357331487),(795916,1085,1355241986),(795992,1046,1355845551),(796012,1085,1355237538),(796066,1045,1357989871),(796182,1046,1355855898),(796278,1045,1355954733),(796293,1046,1355930814),(796293,1085,1355183616),(796621,1085,1355239249),(796658,1085,1355235514),(796772,1045,1357953909),(796990,1085,1355248138),(797096,1046,1355963943),(797106,1085,1355281269),(797294,1045,1357386875),(797341,1046,1355866714),(797437,1046,1355844323),(797467,1045,1355531172),(797489,1085,1355277938),(797567,1046,1355847383),(797668,1046,1355878422),(797853,1085,1355248981),(797929,1045,1355618662),(797954,1085,1355237555),(797967,1085,1355238422),(797986,1046,1355932802),(797989,1046,1357341390),(798028,1045,1355222645),(798086,1085,1355238595),(798118,1085,1355237435),(798288,1045,1358101066),(798394,1085,1355281634),(798476,1045,1357938109),(798659,1045,1356129672),(798720,1046,1355931096),(798985,1045,1357384555),(799217,1045,1357230382),(799309,1046,1357330094),(799684,1085,1355268282),(799877,1045,1355808278),(799895,1046,1355920870),(799905,1046,1355844274),(799905,1085,1355242969),(799919,1045,1355849604),(800186,1085,1355363989),(800283,1046,1355808772),(800292,1045,1355507853),(800306,1046,1355869609),(800421,1085,1355273022),(800503,1085,1355242460),(800611,1085,1355252883),(800616,1046,1355842547),(800787,1045,1358113203),(801061,1085,1355366480),(801082,1085,1355313469),(801426,1085,1355277833),(801506,1085,1355505551),(801657,1085,1355264643),(801664,1085,1355250166),(801707,1045,1357959396),(801707,1046,1355968932),(801716,1085,1355259635),(801731,1085,1355247829),(801788,1085,1355243876),(801849,1046,1355807481),(801953,1085,1355274433),(801978,1046,1357340333),(802263,1046,1356152418),(802263,1085,1355358588),(802348,1046,1355814870),(802777,1046,1355808242),(802787,1045,1357354823),(803074,1045,1355327923),(803074,1085,1355328079),(803098,1085,1355244884),(803270,1045,1357381936),(803470,1085,1355447008),(803593,1085,1355251655),(803660,1085,1355308276),(803877,1085,1355245281),(804037,1085,1355240810),(804189,1085,1355249669),(804201,1085,1355235336),(804316,1046,1355877353),(804431,1046,1355838916),(804661,1085,1355251180),(804667,1045,1355506015),(804713,1236,1355836791),(804832,1046,1357777424),(804957,1085,1355252374),(805060,1085,1355243885),(805420,1045,1357357919),(805614,1045,1357591825),(805654,1085,1355251812),(805708,1085,1355235373),(805860,1046,1355859743),(806141,1085,1355246126),(806197,1046,1355828444),(806300,1046,1357756816),(806445,1085,1355238358),(806743,1045,1358044593),(806790,1085,1355339348),(806870,1085,1355257393),(806960,1085,1355321985),(807084,1046,1357336272),(807278,1085,1355238920),(807321,1045,1355355336),(807321,1046,1355829428),(807477,1046,1357766088),(807642,1046,1355840333),(807711,1085,1355334536),(808110,1045,1355872189),(808132,1046,1355846388),(808229,1046,1355863272),(808260,1085,1355277588),(808297,1045,1356681997),(808365,1046,1357469472),(808422,1085,1355238069),(808430,1085,1355271650),(808500,1046,1357947439),(808561,1045,1357363634),(808730,1085,1355240972),(808752,1085,1355237108),(808760,1085,1355250674),(808804,1236,1355240271),(808830,1085,1355247714),(808847,1085,1355238561),(808887,1085,1355240834),(808911,1085,1355331027),(808942,1085,1355240831),(808951,1085,1355243321),(809001,1045,1356151467),(809001,1085,1355244059),(809008,1085,1355243013),(809037,1085,1355268994),(809108,1046,1357339110),(809136,1085,1355251715),(809146,1085,1355249473),(809162,1085,1355242786),(809333,1045,1357154694),(809338,1085,1355265933),(809341,1045,1357373437),(809341,1227,1357373437),(809364,1085,1355261405),(809372,1085,1355257295),(809613,1046,1357340268),(809626,1085,1355260081),(809641,1085,1355237667),(809711,1085,1355246050),(809749,1085,1355236626),(809751,1085,1355287387),(809857,1085,1355270364),(809868,1085,1355332185),(809876,1085,1355241392),(809880,1085,1355271465),(809888,1085,1355244397),(809924,1085,1355256082),(809926,1085,1355267452),(809982,1085,1355244436),(810012,1045,1357254789),(810033,1085,1355277540),(810098,1085,1355265962),(810126,1085,1355412371),(810214,1085,1355249946),(810250,1085,1355245593),(810266,1085,1355240444),(810276,1085,1355253441),(810291,1045,1355808341),(810349,1085,1355493684),(810369,1085,1355246676),(810410,1045,1358011292),(810410,1085,1355265010),(810460,1085,1355259859),(810476,1085,1355238233),(810501,1046,1355403529),(810518,1085,1355280817),(810542,1045,1357354007),(810559,1045,1357374016),(810559,1085,1355243716),(810582,1046,1355241852),(810652,1085,1355261857),(810658,1085,1355240898),(810679,1085,1355265834),(810700,1046,1355844649),(810727,1085,1355269038),(810775,1085,1355340329),(810837,1085,1355255480),(810855,1085,1355263575),(810958,1085,1355267210),(810983,1085,1355297047),(810999,1046,1357338940),(810999,1085,1355239988),(811079,1085,1355280224),(811100,1085,1355296867),(811121,1046,1355809007),(811121,1085,1355279981),(811198,1045,1357460454),(811198,1085,1355305118),(811217,1046,1355820204),(811265,1085,1355257872),(811280,1046,1355836318),(811303,1085,1355236854),(811356,1085,1355236970),(811383,1045,1357841235),(811383,1085,1355248041),(811392,1085,1355310183),(811466,1085,1355259761),(811480,1085,1355244826),(811483,1085,1355279927),(811493,1085,1355275475),(811515,1085,1355481232),(811522,1085,1355244970),(811523,1085,1355279857),(811537,1085,1355248238),(811562,1045,1357937823),(811562,1085,1355244223),(811600,1085,1355263354),(811613,1085,1355288658),(811669,1085,1355385469),(811698,1085,1355258155),(811719,1045,1357359407),(811736,1085,1355249788),(811820,1085,1355237036),(811857,1085,1355247911),(811904,1046,1357338885),(811969,1085,1355501182),(811985,1045,1357404647),(812034,1085,1355287967),(812064,1085,1355412517),(812081,1085,1355254020),(812114,1085,1355238555),(812183,1046,1357839337),(812202,1085,1355322058),(812263,1045,1355968078),(812446,1045,1357399519),(812506,1045,1357478054),(812512,1085,1355311936),(812728,1085,1355238714),(812780,1085,1355241657),(812962,1085,1355235717),(813140,1085,1355242068),(813213,1046,1355809561),(813427,1085,1355326022),(813507,1045,1355505775),(813769,1045,1356127819),(813858,1085,1355258695),(814036,1046,1355809076),(814162,1046,1355838366),(814184,1046,1355822759),(814220,1046,1357254173),(814249,1045,1357346868),(814249,1085,1355252373),(814271,1085,1355285158),(814330,1085,1355255122),(814881,1085,1355238613),(814985,1045,1355540887),(815172,1085,1355265121),(815336,1046,1355974035),(815390,1085,1355258105),(815436,1046,1355836623),(815456,1045,1358003179),(815474,1046,1355826739),(815562,1045,1357353544),(815949,1046,1355813819),(815971,1085,1355358980),(815973,1085,1355241915),(816029,1046,1355813314),(816114,1046,1355852078),(816129,1085,1355248303),(816203,1046,1355836428),(816309,1046,1357452653),(816376,1085,1355266929),(816510,1045,1357347925),(816609,1046,1356102264),(816774,1046,1355844763),(816930,1045,1355615431),(817240,1085,1355259392),(817252,1085,1355285873),(817339,1046,1355865766),(817744,1045,1357957585),(817950,1046,1357336601),(818015,1046,1355812516),(818037,1046,1355811684),(818099,1085,1355244803),(818170,1085,1355240430),(818236,1045,1357353171),(818241,1085,1355240066),(818320,1046,1355839528),(818338,1046,1355508161),(818401,1045,1356235974),(818401,1085,1355255075),(818407,1045,1355807438),(818410,1046,1355873035),(818671,1085,1355379681),(818705,1046,1355847110),(818849,1085,1355240117),(818867,1046,1355841585),(818966,1045,1355661892),(819259,1085,1355235766),(819379,1046,1355832720),(819563,1046,1355881046),(819660,1085,1355202458),(819808,1045,1357667884),(819833,1046,1355836323),(819836,1046,1357326806),(819973,1085,1355233160),(819992,1046,1355239356),(820067,1085,1355498299),(820158,1045,1357400905),(820196,1045,1355507876),(820211,1046,1355837811),(820408,1046,1355859140),(820629,1045,1358030821),(820643,1046,1355863573),(820676,1046,1355840252),(820701,1085,1355246330),(820710,1085,1355346626),(820740,1085,1355239067),(820782,1046,1357940036),(820806,1046,1355848722),(821168,1046,1355807432),(821368,1045,1356721339),(821457,1085,1355250610),(821607,1046,1355844886),(821612,1085,1355250475),(821626,1046,1355865441),(821639,1046,1355861773),(821696,1045,1357342514),(822072,1085,1355240869),(822116,1046,1355982637),(822241,1045,1356373022),(822241,1085,1355278242),(822356,1085,1355265955),(822364,1045,1358031147),(822415,1085,1355244137),(823029,1085,1355416759),(823051,1085,1355246974),(823054,1085,1355324975),(823095,1085,1355240492),(823124,1046,1355845101),(823188,1045,1358094129),(823188,1227,1358094128),(823188,1236,1356107018),(823211,1046,1355863065),(823212,1085,1355323376),(823238,1085,1355370751),(823327,1085,1355270588),(823414,1046,1355873899),(823485,1085,1355255954),(823547,1045,1357318363),(823702,1045,1357614136),(823753,1046,1355949612),(823901,1045,1355849068),(824019,1045,1356124766),(824026,1085,1355192248),(824057,1045,1357344735),(824274,1045,1355635590),(824305,1045,1357992665),(824346,1045,1355504672),(824483,1045,1355524493),(824558,1085,1355236703),(824559,1085,1355203216),(824601,1045,1355892452),(824680,1085,1355493270),(824693,1046,1355847011),(824841,1046,1355861978),(824924,1085,1355237991),(824980,1085,1355246967),(825006,1046,1356827348),(825034,1046,1355949501),(825236,1045,1357760362),(825319,1046,1355859503),(825460,1045,1357775936),(825620,1045,1357401879),(825621,1085,1355426882),(826293,1045,1355247931),(826293,1085,1355248135),(826326,1046,1355850237),(826817,1046,1356564663),(826844,1085,1355248871),(827091,1085,1355257591),(827139,1085,1355222691),(827179,1045,1358119565),(827246,1085,1355238585),(827259,1085,1355237196),(827263,1085,1355472597),(827296,1085,1355258857),(827369,1045,1357359731),(827421,1045,1357759945),(827428,1085,1355284318),(827509,1085,1355238976),(827724,1045,1355510252),(827732,1085,1355241067),(827786,1046,1355807198),(827810,1085,1355241769),(828022,1045,1356132915),(828068,1046,1355833963),(828167,1046,1355920356),(828214,1046,1358103555),(828294,1046,1357337038),(828397,1085,1355237805),(828451,1045,1355861438),(828451,1046,1355862259),(828838,1045,1357965073),(828848,1046,1357338348),(828859,1045,1357324668),(828888,1045,1357944659),(829003,1085,1355190501),(829085,1046,1355849493),(829126,1085,1355251840),(829325,1085,1355244623),(829429,1085,1355236226),(829580,1046,1355831808),(829634,1046,1355965366),(829664,1085,1355248374),(829688,1045,1356180786),(829723,1046,1355508790),(829774,1046,1355837377),(829930,1045,1357955825),(829942,1046,1357337504),(829963,1085,1355237474),(829974,1045,1357935054),(830152,1085,1355327408),(830171,1085,1355278139),(830356,1085,1355239205),(830588,1085,1355246841),(830649,1085,1355350228),(830658,1045,1355517031),(830658,1085,1355243235),(830961,1045,1358032712),(830999,1045,1357327792),(831057,1085,1355263823),(831065,1045,1358027520),(831185,1046,1355846671),(831318,1045,1355521256),(831328,1085,1355319581),(831488,1045,1356121603),(831583,1085,1355321587),(831597,1045,1357762957),(831607,1085,1355196537),(831702,1045,1358041560),(831746,1046,1355853081),(831867,1045,1357961612),(831922,1046,1355846602),(831933,1045,1356121958),(831951,1046,1355832527),(832118,1045,1355838033),(832160,1045,1356220211),(832236,1085,1355210369),(832308,1085,1355239594),(832369,1085,1355241568),(832402,1085,1355260344),(832425,1045,1357335917),(832425,1046,1355832843),(832474,1085,1355242499),(832481,1085,1355487138),(832510,1085,1355239139),(832513,1085,1355261305),(832521,1085,1355237039),(832575,1085,1355239579),(832604,1085,1355313988),(832612,1085,1355239071),(832640,1045,1357950188),(832640,1227,1357537357),(832640,1236,1355764882),(832650,1045,1357977837),(832669,1046,1355845749),(832706,1085,1355235747),(832795,1045,1357997107),(832814,1085,1355245173),(832821,1085,1355236508),(832905,1085,1355274546),(832958,1045,1355505110),(832958,1046,1355858093),(832999,1085,1355237233),(833030,1085,1355346965),(833065,1046,1355840399),(833080,1085,1355331067),(833091,1085,1355238254),(833132,1085,1355258039),(833156,1046,1355835687),(833165,1045,1356123172),(833182,1046,1355838000),(833207,1085,1355235259),(833282,1085,1355240485),(833341,1085,1355250439),(833372,1085,1355266506),(833379,1045,1357937690),(833455,1085,1355239248),(833471,1085,1355237950),(833498,1085,1355242173),(833540,1085,1355289771),(833567,1085,1355246449),(833599,1046,1355872510),(833700,1085,1355238337),(833820,1085,1355252386),(833850,1085,1355273120),(833855,1085,1355249275),(833867,1085,1355256767),(833920,1085,1355258263),(833984,1085,1355329839),(834014,1045,1355265322),(834014,1085,1355265321),(834055,1085,1355242718),(834153,1085,1355254832),(834211,1045,1357345361),(834231,1085,1355237336),(834285,1085,1355249876),(834290,1085,1355250096),(834316,1085,1355299713),(834375,1085,1355336597),(834414,1085,1355247463),(834458,1085,1355273622),(834467,1085,1355269918),(834536,1085,1355244530),(834564,1085,1355258985),(834595,1085,1355253763),(834649,1085,1355252443),(834705,1085,1355272047),(834723,1085,1355326465),(834725,1045,1355526439),(834725,1085,1355271995),(834753,1045,1357414575),(834876,1085,1355299751),(834947,1085,1355257324),(834965,1085,1355297285),(835027,1085,1355287215),(835036,1046,1356996580),(835052,1085,1355347224),(835057,1046,1355831451),(835123,1046,1355947270),(835180,1085,1355273527),(835215,1085,1355194286),(835222,1046,1355958879),(835227,1085,1355283204),(835509,1045,1357435252),(835594,1085,1355308230),(835598,1085,1355238885),(835615,1085,1355280908),(835658,1085,1355237401),(835719,1045,1355854686),(835915,1236,1357343516),(836030,1085,1355258175),(836074,1045,1355521075),(836123,1085,1355353705),(836137,1085,1355240510),(836279,1085,1355266426),(836302,1046,1355853377),(836796,1046,1357932994),(836895,1046,1355864941),(837094,1045,1355822465),(837275,1085,1355241055),(837385,1046,1356026120),(837439,1046,1355837197),(837442,1045,1356142837),(837829,1045,1357950590),(837843,1046,1355809210),(837880,1045,1357936060),(837990,1085,1355243846),(838088,1085,1355238164),(838189,1045,1357975471),(838310,1085,1355237967),(838408,1045,1357328009),(838665,1085,1355244090),(838994,1046,1355841395),(839099,1085,1355244289),(839129,1046,1355931671),(839250,1085,1355243272),(839306,1045,1355832591),(839306,1227,1355832590),(839350,1046,1355934682),(839562,1045,1356131885),(839587,1085,1355287606),(839688,1046,1355948652),(839726,1046,1355821333),(839742,1046,1355809657),(839975,1085,1355239336),(840081,1045,1357829069),(840083,1046,1355839689),(840278,1045,1355505569),(840344,1085,1355255335),(840625,1085,1355267490),(840754,1045,1355635365),(840766,1045,1357357274),(840967,1046,1355849039),(841074,1046,1357940173),(841085,1085,1355266016),(841268,1045,1355525052),(841358,1046,1355858329),(841507,1046,1357331494),(841529,1045,1357847471),(841588,1085,1355277875),(841651,1046,1355927354),(841782,1045,1357341242),(841831,1045,1355963464),(841982,1085,1355252767),(842006,1046,1355858691),(842012,1046,1355835733),(842076,1085,1355411958),(842279,1046,1355836024),(842283,1046,1355847491),(842362,1046,1355873384),(842774,1045,1357406959),(842972,1085,1355237920),(843004,1045,1357400311),(843557,1045,1358058134),(843557,1236,1356663456),(843650,1046,1357935310),(843732,1045,1358053894),(843895,1046,1357338467),(843997,1045,1358117614),(844049,1046,1357716723),(844895,1085,1355260191),(845173,1046,1355969199),(846692,1046,1355832199),(846908,1045,1357328107),(847340,1046,1355238207),(847340,1085,1355237243),(847589,1045,1357944324),(848091,1046,1355837255),(848219,1085,1355240925),(848236,1085,1355283711),(848563,1046,1357254242),(848601,1045,1355811009),(848601,1227,1355811001),(848601,1236,1358149187),(848957,1046,1357341204),(849014,1045,1356124044),(849492,1046,1355851406),(849500,1045,1357594172),(849798,1045,1356122226),(849805,1085,1355237332),(849872,1085,1355254499),(849968,1046,1357330654),(849988,1046,1355838735),(850005,1045,1358026901),(850054,1046,1355897553),(850359,1045,1355842629),(850411,1045,1355834459),(850641,1045,1355849229),(850663,1046,1355837280),(850748,1085,1355236142),(850851,1046,1355815679),(850855,1085,1355237527),(851034,1045,1358014595),(851322,1046,1355880782),(851605,1045,1355519336),(851639,1045,1355850455),(851650,1046,1355834478),(851809,1045,1358026510),(851848,1045,1357506244),(852239,1046,1355843741),(852371,1045,1357955984),(852442,1046,1357776485),(852542,1046,1355841742),(852636,1046,1355808780),(852768,1045,1355514437),(852835,1045,1357332110),(852896,1046,1355849530),(853468,1085,1355289361),(853614,1045,1356148298),(853813,1085,1355238369),(853909,1045,1357363771),(853909,1085,1355237790),(854058,1085,1355283791),(854314,1085,1355252761),(854351,1045,1357408503),(854480,1045,1357350436),(854480,1046,1355807696),(854638,1085,1355268098),(854765,1045,1355848380),(855245,1045,1356154490),(855411,1046,1355843820),(855535,1046,1357330631),(855902,1045,1357382715),(856062,1085,1355241629),(856117,1045,1355572317),(856331,1046,1355810717),(856417,1045,1357335481),(856417,1227,1357335446),(856478,1046,1355834726),(856507,1045,1355578000),(856680,1045,1358075684),(856681,1045,1357996834),(856684,1045,1357376655),(856700,1045,1356124167),(856886,1085,1355348241),(856892,1046,1355843873),(857148,1085,1355251115),(857596,1046,1355837640),(857681,1046,1355843036),(858000,1046,1355854695),(858798,1046,1355835504),(858841,1046,1355833068),(858943,1085,1355399813),(859019,1085,1355242562),(859061,1046,1355880223),(859143,1085,1355424227),(859259,1046,1355843116),(859267,1046,1355813296),(859276,1045,1357860647),(859458,1085,1355175489),(859679,1085,1355248550),(859848,1045,1357933504),(859978,1046,1357336021),(860051,1046,1356107453),(860111,1045,1357320224),(860277,1045,1355542492),(860466,1046,1355176339),(861206,1045,1355246527),(861258,1045,1357346873),(861281,1045,1357091348),(861522,1046,1355876444),(861667,1046,1357336998),(861747,1045,1355542987),(861832,1085,1355455110),(861883,1046,1355940872),(862377,1046,1357337533),(862534,1046,1357326127),(862608,1085,1355240147),(862662,1045,1358077153),(862662,1046,1358077185),(862768,1085,1355257788),(862916,1045,1358121074),(862953,1045,1358010546),(862967,1046,1357835407),(863170,1046,1355856086),(863199,1046,1357336342),(863628,1046,1355830448),(863631,1045,1356524422),(863694,15095,1356732457),(863770,1046,1355838879),(863781,1046,1355847454),(863870,1045,1355515661),(863959,1045,1357774485),(863959,1236,1356121096),(864056,1045,1355819194),(864066,1045,1355515750),(864066,1085,1355241098),(864215,1045,1357950745),(864335,1046,1355850024),(864366,1045,1356128833),(864458,1085,1355271057),(864479,1045,1357926177),(864533,1085,1355259085),(864699,1045,1355239049),(864699,1085,1355239035),(864717,1236,1356029666),(864721,1085,1355251444),(864760,1045,1356144371),(864808,1046,1356196975),(864846,1046,1355814673),(864919,1085,1355322622),(864970,1085,1355240907),(865000,1045,1357585907),(865043,1045,1355858977),(865043,1236,1356375821),(865067,1045,1356128823),(865179,1045,1357403327),(865209,1045,1357390092),(865243,1046,1356007988),(865253,1045,1355781691),(865295,1046,1355948341),(865425,1045,1357534594),(865498,1046,1355838311),(865573,1045,1357766780),(865584,1045,1357842887),(865755,1045,1357824820),(865767,1085,1355248976),(865836,1045,1355507919),(865991,1085,1355253994),(866011,1045,1357767769),(866137,1085,1355240588),(866338,1046,1355845300),(866908,1046,1357336805),(867196,1045,1355524096),(867463,1046,1356229273),(867948,1046,1357584542),(868590,1045,1357812851),(868590,1046,1357811569),(868690,1046,1355846026),(869009,1085,1355255417),(869138,1046,1355866305),(869191,1046,1355842251),(869465,1046,1355834667),(869768,1045,1357693480),(869770,1046,1355586960),(870211,1046,1356049747),(870288,1085,1355285527),(870320,1046,1355860418),(870352,1046,1355864673),(870412,1085,1355248931),(870575,1046,1356102079),(870847,1045,1357387795),(870855,1045,1355819737),(870855,1046,1355819173),(870940,1085,1355243487),(870947,1085,1355184561),(871043,1085,1355261156),(871079,1046,1355864347),(871278,1085,1355273401),(871334,1045,1357324518),(871334,1227,1357324515),(871334,1236,1357324466),(871417,1046,1357341103),(871433,1046,1357337719),(871610,1045,1357411300),(871771,1046,1355953191),(872034,1046,1355808558),(872046,1045,1357934224),(872130,1045,1357932838),(872377,1046,1356599143),(872377,1085,1355212961),(872512,1085,1355236153),(872674,1046,1357324087),(872678,1045,1355503007),(872905,1046,1355809708),(872929,1046,1355887870),(872931,1085,1355244073),(872965,1085,1355242349),(872993,1046,1355970984),(873018,1045,1355605951),(873246,1085,1355458524),(873374,1045,1356144856),(873378,1046,1355827950),(873420,1045,1357328042),(873451,1046,1356148435),(873621,1046,1355831479),(873661,1046,1355854303),(874161,1045,1357403862),(874288,1085,1355237300),(874431,1046,1355831382),(874443,1085,1355236274),(874665,1085,1355435587),(874672,1046,1355831173),(874836,1046,1355849370),(874848,15077,1356383383),(875088,1046,1355807779),(875288,1045,1357369315),(875595,1046,1355852362),(875695,1045,1355507225),(875966,1045,1357351431),(876039,1046,1355811016),(876112,1046,1355808006),(876237,1045,1357947133),(876542,1085,1355254454),(876760,1045,1357493425),(876938,1085,1355264194),(876990,1046,1355831549),(877245,1046,1355847415),(877249,1045,1355531228),(877431,1046,1356019849),(877537,1046,1355858306),(877619,1046,1356019809),(877726,1046,1355878440),(877811,1085,1355246352),(877827,1045,1357939830),(877834,1045,1357405598),(877834,1236,1357405511),(877874,1085,1355506064),(878188,1085,1355243732),(878210,1045,1357763104),(878485,1046,1355838261),(878502,1045,1355507237),(878696,1085,1355243425),(878711,1045,1355605675),(878743,1045,1357932233),(878751,1045,1357964774),(878768,1085,1355244787),(878788,1045,1357327664),(878837,1085,1355244243),(878933,1085,1355358183),(878946,1045,1356140998),(878979,1045,1357957286),(879319,1046,1357337617),(879376,1085,1355261701),(879408,1045,1355345170),(879632,1045,1357408294),(879793,1045,1357267422),(879834,1046,1355836831),(879846,1085,1355236438),(879865,1085,1355270067),(879873,1085,1355320203),(879935,1046,1355842560),(879963,1085,1355237686),(879968,1085,1355236055),(880014,1085,1355237749),(880051,1085,1355235843),(880064,1046,1355814990),(880064,1085,1355235545),(880148,1085,1355253747),(880219,1046,1355838870),(880219,1085,1355238512),(880255,1045,1357939259),(880255,1046,1355837491),(880255,11949,1357938932),(880260,1045,1355244099),(880260,1085,1355244079),(880390,1085,1355236741),(880407,1045,1355516122),(880407,1085,1355235277),(880419,1045,1355347306),(880423,1085,1355237601),(880456,1045,1356123143),(880478,1085,1355239604),(880515,1085,1355237636),(880519,1085,1355284930),(880529,1085,1355260547),(880632,1085,1355236838),(880655,1085,1355277968),(880779,1085,1355237786),(880828,1045,1355523165),(880847,1085,1355236546),(880869,1085,1355243324),(880916,1046,1355839790),(880955,1046,1355936065),(880989,1085,1355257436),(881010,1046,1355860686),(881036,1085,1355239681),(881039,1045,1355535010),(881063,1085,1355241186),(881136,1085,1355274157),(881276,1085,1355257528),(881342,1085,1355236841),(881358,1085,1355237091),(881399,1045,1356100402),(881536,1085,1355271472),(881545,1085,1355236236),(881582,1085,1355238934),(881594,1085,1355282383),(881605,1085,1355235366),(881618,1085,1355279200),(881807,1085,1355247533),(881873,1045,1357327977),(881930,1085,1355254259),(881940,1085,1355245373),(881943,1046,1355841069),(881977,1085,1355237855),(881978,1085,1355249524),(881991,1085,1355240214),(882025,1085,1355237168),(882035,1085,1355242401),(882160,1085,1355249030),(882172,1085,1355239717),(882200,1085,1355316520),(882225,1046,1355834036),(882231,1045,1355535887),(882418,1085,1355338669),(882525,1085,1355274121),(882545,1085,1355240247),(882566,1045,1355510136),(882578,1085,1355244702),(882596,1085,1355413425),(882623,1046,1355847565),(882664,1046,1355810577),(882669,1045,1355686208),(882711,1085,1355240428),(882719,14,1356042845),(882726,1085,1355271019),(882774,1046,1355868573),(882825,1085,1355257871),(882836,1046,1355808115),(882845,1085,1355236283),(882912,1045,1355584299),(882935,1085,1355242695),(882971,1045,1357512214),(882984,1085,1355347373),(883043,1085,1355243397),(883168,1046,1355846490),(883176,1046,1355834578),(883213,1046,1355844516),(883250,1085,1355329720),(883504,1085,1355328875),(883541,1046,1355845378),(883541,1085,1355244549),(883578,1085,1355237648),(883597,1045,1356119815),(883622,1046,1355848711),(883670,1085,1355247344),(883737,1045,1357476381),(883776,1085,1355258367),(883790,1085,1355239755),(883852,1085,1355242320),(883870,1046,1355839603),(883887,1085,1355244887),(883911,1046,1355807518),(883916,1085,1355269032),(883926,1046,1355835055),(883943,1085,1355330420),(884098,1085,1355340888),(884106,1045,1355505391),(884152,1045,1355630675),(884152,1085,1355250363),(884189,1085,1355240772),(884208,1085,1355237431),(884239,1085,1355312856),(884308,1085,1355249843),(884358,1085,1355256531),(884393,1085,1355239416),(884396,1045,1357325367),(884423,1046,1355842825),(884423,1085,1355259645),(884443,1046,1355864127),(884467,1085,1355244275),(884493,1045,1357360037),(884523,1085,1355244883),(884524,1085,1355269703),(884555,1085,1355255728),(884580,1045,1357620074),(884580,1046,1356583959),(884611,1046,1355854453),(884700,1045,1355885946),(884741,1045,1356121516),(884743,1046,1355829176),(884786,1085,1355277679),(884813,1046,1355841474),(884884,1046,1355854798),(884919,1085,1355314543),(884923,1046,1355844657),(884941,1085,1355242716),(884965,1046,1355843496),(884997,1046,1355835794),(885014,1085,1355285138),(885049,1085,1355264955),(885056,1085,1355264711),(885123,1085,1355266827),(885172,1046,1355870289),(885182,1085,1355260551),(885183,1085,1355318149),(885188,1046,1355876770),(885194,1085,1355278586),(885354,1085,1355256975),(885395,1085,1355272540),(885419,1085,1355237841),(885471,1046,1356058928),(885498,1045,1357329466),(885501,1085,1355278132),(885533,1046,1355940455),(885552,1085,1355246143),(885560,1085,1355246472),(885580,1046,1355833867),(885647,1085,1355236311),(885655,1085,1355243258),(885664,1085,1355243799),(885672,1085,1355244903),(885682,1046,1355276804),(885753,14,1355377287),(885776,1042,1357341179),(885776,1046,1357341181),(885845,1085,1355240115),(885871,1046,1355849366),(885875,1085,1355352438),(885904,1046,1355812297),(885956,1046,1355810202),(885987,1046,1355888686),(885992,1085,1355289858),(886039,1046,1355807223),(886041,1046,1355810220),(886087,1046,1355939541),(886092,1045,1357953578),(886100,1045,1357327734),(886124,1085,1355320043),(886159,1085,1355319127),(886247,1046,1355846378),(886349,1085,1355237758),(886413,1046,1355884781),(886416,1085,1355259481),(886546,1046,1355809163),(886558,1045,1357331516),(886564,1046,1355816862),(886564,1085,1355328514),(886576,1085,1355245173),(886585,1045,1358030700),(886618,1085,1355265197),(886623,1045,1357347839),(886738,1045,1357366294),(886774,1236,1357448041),(886785,1085,1355321960),(886884,1045,1357883422),(886904,1045,1358003084),(887130,1045,1357225765),(887237,1046,1355838325),(887268,1085,1355272433),(887377,1046,1355829168),(887379,1085,1355289984),(887390,1085,1355238176),(887409,1046,1355856073),(887425,1085,1355273908),(887431,1045,1358016155),(887431,1046,1358016217),(887465,1085,1355356652),(887553,1045,1357311409),(888389,1085,1355247752),(888942,1085,1355238204),(889018,1045,1356128394),(889147,1045,1357334030),(889447,1046,1355858191),(889737,1045,1356122063),(889737,1085,1355236134),(889983,1046,1355813638),(889987,1046,1355836847),(889990,1046,1357337054),(890129,1046,1357324152),(890132,1085,1355249481),(890214,1045,1357938561),(890336,1045,1357328459),(890562,1085,1355239810),(890628,1085,1355240494),(890732,1045,1355507920),(890736,1046,1355808565),(890818,1045,1356122465),(890818,1046,1355867579),(890822,1045,1355585114),(890840,1046,1355835313),(890841,1085,1355270033),(891027,1046,1355852440),(891070,1046,1355848772),(891127,1046,1355809119),(891143,1046,1355850022),(891157,1046,1355828885),(891190,1046,1356008472),(891227,1046,1355847724),(891259,1046,1357100035),(891299,1046,1355840564),(891308,1046,1355831632),(891384,1045,1355867801),(891436,1085,1355237348),(891467,1046,1355845515),(891544,1046,1355835555),(891570,1046,1355828866),(891739,1046,1355361005),(891788,1046,1355839028),(892125,1085,1355200222),(892155,1085,1355283832),(892188,1045,1357946491),(892203,1046,1355806187),(892236,1045,1357365838),(892368,1045,1355527517),(892417,1046,1355845426),(892464,1085,1355243456),(892496,1046,1355874933),(892587,1045,1357348049),(892598,1045,1358013313),(892621,1085,1355279397),(892804,1085,1355290989),(892941,1046,1355813521),(893016,1085,1355245969),(893030,1046,1355808231),(893043,1045,1356122665),(893321,1046,1357322983),(893385,1046,1355837079),(893439,1046,1355854345),(893449,1046,1355838899),(893463,1046,1357339045),(893470,1046,1355809393),(893491,1046,1355844103),(893554,1046,1355842162),(893557,1046,1357934657),(893591,1046,1355831296),(893814,1046,1355846092),(893866,1045,1357327758),(893871,1046,1355838745),(894147,1236,1355858085),(894194,1046,1356376487),(894329,1046,1355844474),(894553,1046,1355814632),(894561,1046,1355819006),(894564,1085,1355267712),(894664,1046,1355966567),(894715,1046,1356556325),(894813,1045,1357353184),(895090,1046,1355834607),(895286,1045,1355348368),(895369,1045,1357327400),(895481,1045,1357956995),(895517,1046,1355886067),(895717,1085,1355240537),(895754,1085,1355339363),(895765,1046,1355838061),(895855,1046,1355839353),(895987,1046,1355891024),(896161,1046,1356029931),(896231,1046,1355518718),(896345,1045,1357937773),(896425,1046,1355859630),(896444,1046,1355861059),(896462,1085,1355348845),(896692,1085,1355268555),(896721,1046,1355838818),(896771,1046,1355861226),(896793,1046,1356107272),(897001,1046,1355849286),(897174,1045,1355859367),(897209,1046,1355875901),(897212,1045,1357942039),(897391,1046,1355845107),(897453,1046,1355865655),(897534,1045,1357592122),(897815,1045,1358014260),(897882,1046,1355812359),(897922,1045,1356128869),(898108,1046,1355835937),(898173,1046,1356031011),(898215,1046,1355851058),(898355,1045,1357365686),(898509,1046,1355932202),(898536,1046,1355890712),(898571,1046,1356359114),(898583,1085,1355273875),(898654,1046,1355844569),(898694,1045,1358036158),(898780,1046,1357338288),(899008,1045,1357402442),(899115,1046,1355942004),(899161,1046,1357338153),(899486,1045,1357951800),(899575,1045,1356207297),(899575,1046,1356037090),(899632,1085,1355503266),(899690,1045,1355859563),(899741,1085,1355359840),(899934,1046,1355843293),(899946,1085,1355263906),(899949,1085,1355247450),(900011,1046,1357339342),(900138,1046,1357321201),(900143,1045,1355351057),(900199,1045,1358011263),(900254,1046,1356042880),(900325,1045,1355694483),(900411,1045,1356135585),(900537,1046,1355862352),(900553,1045,1357956208),(900837,1085,1355248643),(901166,1046,1355836177),(901270,1046,1355833466),(901338,1085,1355292675),(901365,1046,1355828117),(901416,1045,1357439674),(901775,1085,1355251202),(901915,1046,1355839145),(901964,1045,1355522964),(902097,1046,1355970161),(902144,1046,1355809734),(902173,1046,1357336487),(902208,1045,1356157261),(902234,1046,1355867825),(902303,1046,1355840715),(902329,1045,1357400301),(902360,1045,1357350178),(902491,1045,1356372449),(902529,1046,1355840158),(902673,1046,1355849281),(902685,1046,1357932680),(902728,1045,1355188395),(902728,1085,1355188375),(902848,1046,1357336531),(903046,1046,1355856839),(903146,1046,1355864584),(903153,1046,1355841004),(903224,1046,1355846928),(903312,1045,1357417941),(903404,1045,1357337215),(903404,1046,1357337211),(903415,1046,1355809497),(903459,1045,1357410235),(903462,1046,1355841442),(903505,1085,1355252224),(903650,1085,1355236405),(903774,1046,1355837084),(903821,1085,1355246292),(904069,1045,1357763321),(904304,1045,1355362034),(904340,1045,1356286555),(904420,1046,1355811991),(904420,1085,1355350944),(904433,1045,1355527738),(904665,1046,1355836895),(904813,1046,1355813705),(904818,1045,1358034892),(904818,1046,1355805921),(904829,1046,1355839079),(904905,1046,1355856863),(904963,1046,1355809362),(905027,1046,1355926539),(905127,1046,1355853135),(905289,1046,1355811641),(905296,1045,1357969781),(905329,1085,1355283418),(905350,1045,1357436326),(905413,1046,1355940221),(905517,1085,1355236433),(905808,1045,1358036373),(905822,1046,1355807987),(905869,1046,1355815755),(905961,1085,1355255386),(906045,1046,1355822638),(906123,1046,1355808580),(906143,1045,1355505503),(906209,1045,1357961256),(906221,1046,1355830146),(906419,1045,1357327133),(906570,1046,1355846747),(906702,1046,1355847590),(906704,1085,1355508515),(906717,14,1357943125),(906745,1085,1355424635),(906746,1046,1355838004),(906761,1046,1355932381),(906968,1046,1355841735),(907053,1085,1355238531),(907146,1045,1358026516),(907256,1085,1355242392),(907285,1045,1356179253),(907296,1046,1357309708),(907402,1045,1356121507),(907402,1046,1355835731),(907410,1046,1355845725),(907484,1046,1355921132),(907502,1085,1355238079),(907570,1046,1355932947),(907588,1046,1357152954),(907638,1085,1355248687),(907822,1085,1355238920),(907834,1046,1355849508),(908098,1045,1355841654),(908100,1046,1355806979),(908142,1085,1355236886),(908265,1085,1355321654),(908436,1045,1357405709),(908483,1046,1355847642),(908519,1045,1357353512),(908535,1085,1355273865),(908563,1046,1355964057),(908622,1046,1355868612),(908634,1046,1355869917),(908704,1045,1355527671),(908707,1046,1355854756),(908714,1045,1355509399),(908748,1046,1355959108),(908830,1046,1356740872),(908837,1085,1355236856),(908841,1046,1355953881),(908845,1045,1356124438),(908907,1046,1355869863),(908968,1045,1357350867),(909014,1045,1355519991),(909071,1046,1355851811),(909146,1085,1355235522),(909149,1236,1355583684),(909160,1046,1355516013),(909181,1045,1355512767),(909227,1046,1355863625),(909227,1085,1355254179),(909228,1085,1355174851),(909250,1045,1355971689),(909295,1046,1355867356),(909389,1045,1357335510),(909400,1046,1355818310),(909480,1045,1357939118),(909488,1045,1356816388),(909506,1045,1358004884),(909553,1046,1355953462),(909605,1046,1356005506),(909773,1046,1355837261),(909799,1045,1356176994),(909799,1046,1355839261),(909836,1045,1355584741),(909885,1045,1357959292),(909885,1046,1355846952),(909921,1085,1355245716),(909930,1085,1355416577),(909967,1046,1356544445),(910171,1045,1357950589),(910194,1046,1355854038),(910219,1085,1355286733),(910223,1045,1357948254),(910223,1046,1355824907),(910233,1046,1356057647),(910240,1046,1357340682),(910273,1045,1357335600),(910312,1085,1355249578),(910355,1045,1357385234),(910355,1046,1355832261),(910360,1046,1355841888),(910376,1046,1355836522),(910397,1046,1355858124),(910421,1046,1355850156),(910462,1045,1355845683),(910464,1085,1355248166),(910478,1045,1357406079),(910671,1085,1355281773),(910689,1085,1355286576),(910691,1085,1355238246),(910732,1085,1355281519),(910735,1046,1355840549),(910756,1085,1355273207),(910779,1085,1355236231),(910803,1085,1355236835),(910815,1045,1355834978),(910820,1046,1357934400),(910820,1085,1355237808),(910851,1085,1355237149),(910876,1085,1355239474),(910890,1085,1355236795),(910932,1085,1355241486),(910961,1046,1355805975),(910985,1085,1355235451),(911002,1045,1357385283),(911017,1085,1355315777),(911045,1085,1355263463),(911053,1045,1355250517),(911053,1085,1355246190),(911053,1227,1355250516),(911137,1085,1355238423),(911140,1046,1355841437),(911153,1085,1355235878),(911161,1085,1355325577),(911164,1085,1355236322),(911205,1085,1355256784),(911212,1085,1355246681),(911264,1046,1355826828),(911328,1046,1357323780),(911341,1085,1355258224),(911360,1085,1355236989),(911386,1046,1355241181),(911386,1085,1355241211),(911418,1046,1357336194),(911477,1045,1357933625),(911487,1085,1355249232),(911505,1046,1355844789),(911561,1046,1355841474),(911579,1085,1355237869),(911596,1085,1355272758),(911629,1085,1355239930),(911632,1085,1355240529),(911651,1046,1355848971),(911657,1085,1355282617),(911680,1085,1355253841),(911688,1085,1355337297),(911693,1046,1355839989),(911701,1085,1355243392),(911740,1085,1355237900),(911742,1046,1357336325),(911770,1085,1355239818),(911800,1045,1355243702),(911800,1085,1355243685),(911873,1085,1355236360),(911882,1085,1355264490),(911981,1045,1357331332),(912048,1085,1355287926),(912189,1085,1355252230),(912206,1085,1355250292),(912266,1045,1355770766),(912266,1046,1355857498),(912275,1085,1355417100),(912388,1085,1355256870),(912397,1085,1355238789),(912400,1085,1355254447),(912542,1046,1355837863),(912569,1085,1355287400),(912580,1045,1357844590),(912909,1085,1355328395),(912927,1045,1355626199),(913290,1045,1355808301),(913298,1085,1355282592),(913490,1045,1357328053),(914100,1045,1357940072),(914156,1085,1355268745),(914220,1046,1355819661),(914231,1085,1355272303),(914637,1045,1358015388),(914780,1085,1355358025),(914949,1085,1355350198),(915020,1085,1355247644),(915381,1045,1355856201),(915932,1085,1355235146),(916292,1085,1355456585),(916580,1085,1355270661),(916591,1046,1355887755),(916628,1046,1355659491),(917365,1236,1355828057),(918312,1046,1355839985),(918980,1046,1355849088),(920152,1085,1355243132),(920579,1045,1355867736),(921413,1046,1355840025),(921530,1045,1355807507),(921924,1045,1357937517),(922525,1045,1355843278),(922708,1046,1355847308),(923007,1046,1355807435),(923733,1045,1355830751),(924266,1236,1356112935),(924336,1085,1355266416),(924426,1045,1355843785),(924465,1046,1355827075),(925053,1046,1355863074),(925287,1046,1357339826),(925593,1236,1355838548),(925941,1085,1355273407),(926401,1085,1355261606),(926646,1085,1355336448),(926652,1085,1355236501),(926884,1085,1355259711),(926969,1045,1357951580),(926983,1085,1355243514),(926986,1045,1355843880),(926986,1046,1355843670),(927155,1046,1355836120),(927225,1085,1355238046),(927607,1045,1355852813),(927743,1046,1355840404),(927849,1046,1357336040),(927849,1236,1355857130),(927856,1046,1355864446),(927896,1085,1355244275),(928233,1045,1357369041),(928460,1085,1355275532),(928620,1085,1355266535),(928859,1046,1357336216),(928920,1085,1355266080),(930872,1085,1355187996),(931415,1046,1355837766),(931603,1046,1355833558),(931604,1085,1355235988),(931996,1046,1355887758),(933021,1046,1355982278),(933027,1085,1355239270),(933318,1045,1355852593),(933318,1046,1355850601),(933318,1227,1355852580),(933318,1236,1355852785),(934081,1046,1355847919),(934378,1236,1356129890),(935726,1046,1355812178),(935755,1046,1355894535),(935976,1085,1355235537),(936294,1045,1355849759),(937333,1046,1355841833),(937734,1045,1357959107),(938504,1046,1355848667),(938570,1045,1355835405),(938578,1045,1357011433),(938631,1046,1355497334),(938711,1046,1355844907),(938793,1046,1355807540),(938966,1045,1357935504),(939007,1046,1356120199),(939423,1045,1355807745),(939609,1045,1357554655),(939609,1227,1357554649),(939609,1236,1357554608),(939949,1045,1355859044),(939949,1227,1355859043),(940018,1236,1357325468),(940135,1085,1355314291),(940252,1045,1357869885),(940380,1046,1355836014),(940420,1046,1355858037),(941630,1085,1355236486),(941861,1046,1357341538),(941879,1046,1355847242),(941940,1085,1355193248),(942292,1046,1355898185),(942424,1236,1357334136),(942822,1046,1355838138),(943337,1046,1355840172),(943825,1045,1355848859),(944891,1046,1357338140),(944913,1046,1356029140),(945233,1040,1357938203),(945233,1042,1357938114),(945233,1045,1357938204),(945589,1040,1357594694),(945589,1045,1357594696),(945597,1236,1357431016),(945619,1045,1357335553),(945619,1046,1355808921),(945748,1085,1355264948),(945765,11937,1357935567),(945894,1085,1355238829),(945899,1085,1355279546),(945935,1046,1355838646),(946026,1046,1355833997),(946148,1045,1357326133),(946580,1085,1355239417),(946598,1045,1355839522),(946616,1085,1355238358),(946704,1085,1355238556),(946847,1085,1355245548),(946866,1046,1355845133),(946960,1046,1356033332),(947225,1236,1355253862),(947225,11937,1355253531),(947449,1085,1355241816),(947538,1045,1357269709),(947538,1236,1357269659),(947552,1046,1355847415),(947639,1045,1357345160),(947639,1046,1357345131),(947704,1085,1355284757),(947757,1085,1355276421),(947818,1046,1355583804),(947932,1046,1355839823),(947963,1085,1355250381),(948060,1085,1355243430),(948119,1085,1355247440),(948596,1046,1355861438),(948742,1046,1355823310),(948765,1085,1355237248),(948768,1085,1355250600),(948848,1085,1355312141),(948887,1085,1355246624),(948924,1046,1355844746),(949045,1045,1357584473),(949144,1045,1355869717),(949215,1085,1355237418),(949283,1046,1356083360),(949658,1046,1355843012),(949759,1085,1355255461),(949936,1085,1355248027),(949944,1046,1356011881),(950217,1085,1355288508),(950257,1085,1355281253),(950324,1045,1355885057),(950374,1085,1355264610),(950406,1046,1355275046),(950707,1046,1355879705),(950958,1045,1357960158),(950958,1085,1355272670),(950967,1046,1355880933),(951298,1046,1355861968),(951336,1046,1358093570),(951429,1085,1355276064),(951480,1085,1355241457),(952010,1045,1357328010),(952212,1085,1355237938),(953157,1236,1357744552),(953677,1236,1355831121),(953883,1045,1357983952),(954483,1045,1357326694),(954488,1046,1355849542),(955084,1085,1355280126),(955189,1046,1355835476),(956407,1046,1357938235),(956432,1085,1355287829),(957446,1046,1355840818),(958476,1045,1357988026),(958618,1045,1355348076),(959025,1045,1355847012),(959500,1046,1355808052),(959702,1085,1355238394),(959749,1046,1355841826),(960519,1236,1356923710),(960748,1045,1355840866),(961051,1085,1355290428),(961622,1085,1355372471),(962014,1045,1357778979),(962014,1085,1355332718),(962043,1046,1355811756),(962234,1085,1355249330),(963181,1085,1355433965),(963467,1046,1355808962),(964066,1045,1357952374),(964331,1046,1355832294),(964776,1085,1355245643),(965214,1046,1356065002),(965615,1046,1355839451),(965803,1046,1357334853),(965803,1236,1357334936),(966365,1046,1357326597),(966796,1046,1355927807),(967174,1046,1355866979),(967617,1046,1357935106),(967668,1045,1355835379),(968216,1085,1355248486),(968537,1045,1355827665),(968539,1085,1355416182),(969086,1046,1355975498),(969249,1046,1357326799),(969249,1236,1357326684),(969933,1040,1355918010),(969933,1045,1355918012),(969995,1046,1355836183),(970277,1046,1355862201),(970536,1046,1355961542),(970774,1045,1355514435),(970866,1045,1357952831),(971538,1046,1355485700),(971620,1045,1356142518),(971732,1046,1355809072),(971950,1045,1357962824),(971950,1046,1357340295),(972066,1046,1356053233),(972104,1236,1358020653),(972224,1046,1355970852),(972776,1045,1357372219),(972849,1085,1355262504),(972860,1046,1355821098),(972862,1046,1357109042),(973152,1046,1355935407),(974151,1046,1357336082),(974440,1045,1357389237),(974440,1236,1355841901),(974463,1046,1355850248),(974535,1236,1357343892),(974985,1085,1355329786),(975068,1085,1355362663),(975106,1045,1357934518),(975786,1046,1357334658),(975786,1085,1355262733),(975807,1046,1355856599),(975889,1085,1355279781),(975905,1046,1357340362),(975920,1045,1355363032),(975939,1046,1357341489),(975958,1046,1357132292),(976048,1046,1357255113),(976193,1045,1358002927),(976216,1046,1355845225),(976294,1046,1355867382),(976460,1046,1355842807),(976460,1236,1355843424),(976578,1046,1355852616),(976642,1045,1355871437),(976651,1085,1355244025),(976762,1045,1355881584),(976814,1045,1355935136),(976872,1045,1357592026),(977076,1046,1355988168),(977151,1045,1355435908),(977153,1046,1355656984),(977182,1045,1357543446),(977182,1046,1358154586),(977182,1227,1356161950),(977182,15033,1355817470),(977217,1045,1355854375),(977536,1085,1355200659),(978129,1046,1355964874),(978397,1046,1355837862),(978407,1085,1355241035),(978531,1045,1355539144),(978531,1085,1355348841),(978712,1085,1355257211),(978808,1046,1355359634),(978896,1045,1355870136),(978896,1046,1355870024),(979019,1085,1355238963),(979267,1046,1357340513),(979666,1046,1355869867),(979666,1236,1357154333),(979722,1085,1355266045),(979895,1045,1355891057),(980267,1045,1355876536),(980312,1046,1355808517),(980330,1046,1355837182),(980429,1046,1356305105),(980543,1046,1355851404),(980604,1046,1355846708),(980861,1236,1357330394),(980897,1085,1355353074),(980945,1046,1357965044),(981557,1046,1355915155),(982216,1085,1355274258),(982216,1236,1355810655),(982258,1046,1355846979),(982822,1046,1355840310),(983259,1046,1355846324),(983304,1046,1355825605),(983375,1045,1355843375),(983733,1085,1355436899),(984942,1046,1357336075),(985001,1045,1355872036),(985333,1045,1355816872),(985423,1085,1355247370),(985429,1085,1355240302),(985437,1046,1355196912),(985453,1045,1357073030),(985453,1085,1355174900),(985454,1085,1355175059),(985455,1085,1355175386),(985456,1085,1355175662),(985457,1085,1355176318),(985458,1085,1355176606),(985459,1085,1355176754),(985460,1085,1355176899),(985461,1085,1355177242),(985462,1085,1355177971),(985463,1085,1355177992),(985465,1085,1355178779),(985466,1085,1355179118),(985467,1085,1355179278),(985468,1085,1355179944),(985469,1045,1355180261),(985469,1085,1355180248),(985470,1085,1355180309),(985471,1085,1355180854),(985472,1085,1355181403),(985473,1085,1355181956),(985474,1085,1355182104),(985475,1085,1355182226),(985476,1085,1355182777),(985477,1085,1355183132),(985478,1085,1355184066),(985479,1085,1355184618),(985480,1085,1355184868),(985481,1085,1355185007),(985482,1085,1355185250),(985483,1085,1355185277),(985484,1085,1355185469),(985485,1085,1355186161),(985486,1085,1355188879),(985487,1085,1355190862),(985488,1085,1355191841),(985489,1085,1355192149),(985490,1085,1355193461),(985491,1085,1355194241),(985492,1085,1355194421),(985493,1085,1355194543),(985494,1085,1355195527),(985495,1085,1355196215),(985496,1085,1355237648),(985497,1085,1355196757),(985498,1085,1355197468),(985499,1085,1355198300),(985500,1085,1355198791),(985502,1046,1356796375),(985502,1085,1355200792),(985503,1085,1355201472),(985505,1085,1355203855),(985506,1085,1355205036),(985507,1085,1355206238),(985508,1085,1355208219),(985509,1085,1355209418),(985510,1085,1355211596),(985511,1085,1355211962),(985512,1085,1355224145),(985513,1085,1355224424),(985514,1085,1355224931),(985515,1085,1355231966),(985516,1085,1355232975),(985517,1085,1355233418),(985518,1085,1355234656),(985519,1085,1355234771),(985520,1085,1355234888),(985521,1085,1355234892),(985522,1085,1355234912),(985523,1085,1355234941),(985524,1085,1355234958),(985525,1085,1355234974),(985526,1085,1355234999),(985527,1085,1355235096),(985528,1085,1355235101),(985529,1085,1355235119),(985530,1085,1355235125),(985531,1085,1355235139),(985532,1085,1355235148),(985533,1085,1355235151),(985534,1085,1355235161),(985535,1085,1355235200),(985536,1085,1355235218),(985537,1085,1355235234),(985538,1085,1355235237),(985539,1085,1355235237),(985540,1085,1355235251),(985541,1085,1355235258),(985542,1085,1355235280),(985543,1085,1355235304),(985544,1085,1355235312),(985545,1085,1355235315),(985546,1085,1355235316),(985547,1085,1355235323),(985548,1085,1355235382),(985549,1085,1355235342),(985550,1085,1355235376),(985551,1085,1355235361),(985552,1085,1355235363),(985553,1085,1355235379),(985554,1085,1355235383),(985555,1085,1355235389),(985557,1085,1355235398),(985558,1085,1355235400),(985559,1085,1355235401),(985560,1046,1355235594),(985560,1085,1355235404),(985561,1085,1355235418),(985562,1085,1355235441),(985563,1085,1355235479),(985564,1085,1355235480),(985565,1085,1355333238),(985566,1085,1355235495),(985567,1085,1355235501),(985568,1085,1355235502),(985569,1085,1355235522),(985570,1085,1355235526),(985571,1085,1355235527),(985572,1085,1355235528),(985573,1085,1355235539),(985574,1085,1355235548),(985575,1085,1355235552),(985576,1085,1355235555),(985577,1085,1355235557),(985578,1085,1355235569),(985579,1085,1355235570),(985580,1085,1355235575),(985581,1085,1355235584),(985582,1085,1355235597),(985583,1085,1355235636),(985584,1085,1355278588),(985585,1085,1355235619),(985586,1085,1355235622),(985587,1085,1355235636),(985588,1085,1355235639),(985589,1085,1355235640),(985590,1085,1355235641),(985591,1085,1355235643),(985592,1085,1355235644),(985593,1085,1355235645),(985594,1085,1355235652),(985595,1085,1355235663),(985596,1085,1355235664),(985597,1085,1355235664),(985598,1085,1355235664),(985599,1085,1355235665),(985600,1085,1355235670),(985601,1085,1355235672),(985602,1085,1355235679),(985603,1085,1355235681),(985604,1085,1355235684),(985605,1085,1355235685),(985606,1085,1355235688),(985607,1085,1355235693),(985608,1085,1355235700),(985609,1085,1355235773),(985610,1085,1355235718),(985611,1085,1355235719),(985612,1085,1355235721),(985613,1085,1355235721),(985614,1085,1355235725),(985615,1085,1355235743),(985616,1085,1355235748),(985617,1085,1355235751),(985618,1085,1355235754),(985619,1085,1355235764),(985620,1085,1355235767),(985621,1085,1355235772),(985622,1085,1355235779),(985623,1085,1355235792),(985624,1085,1355235794),(985625,1085,1355235795),(985626,1085,1355235798),(985627,1085,1355235804),(985628,1085,1355235886),(985629,1085,1355235809),(985630,1085,1355235816),(985631,1085,1355235827),(985632,1085,1355235827),(985633,1085,1355235834),(985634,1085,1355235839),(985635,1085,1355235847),(985636,1085,1355235854),(985637,1085,1355235857),(985638,1085,1355235858),(985639,1085,1355235858),(985640,1085,1355235861),(985641,1085,1355235867),(985642,1085,1355235875),(985643,1085,1355237658),(985644,1045,1355235901),(985644,1085,1355235891),(985645,1085,1355235894),(985646,1085,1355235895),(985647,1085,1355235898),(985648,1085,1355235906),(985649,1085,1355235907),(985650,1085,1355235910),(985651,1085,1355235911),(985652,1085,1355239452),(985653,1085,1355235916),(985654,1085,1355236208),(985654,1236,1355236108),(985655,1085,1355235927),(985656,1085,1355235935),(985657,1085,1355235936),(985658,1085,1355235943),(985659,1085,1355235943),(985660,1085,1355235947),(985661,1085,1355235952),(985662,1085,1355235963),(985663,1085,1355235964),(985664,1085,1355235979),(985664,1236,1355237137),(985665,1085,1355235991),(985666,1085,1355235994),(985667,1085,1355236072),(985668,1085,1355236002),(985669,1085,1355236003),(985670,1085,1355236006),(985671,1085,1355236007),(985672,1085,1355236008),(985673,1085,1355236011),(985674,1085,1355236011),(985675,1085,1355236014),(985676,1085,1355236017),(985677,1085,1355236018),(985678,1085,1355236019),(985679,1085,1355236019),(985680,1085,1355236022),(985681,1085,1355236023),(985682,1085,1355236029),(985683,1085,1355236108),(985684,1085,1355236037),(985685,1085,1355236047),(985686,1085,1355236049),(985687,1085,1355236053),(985688,1085,1355236055),(985689,1085,1355236058),(985690,1085,1355236181),(985691,1085,1355236071),(985692,1085,1355236078),(985693,1085,1355236079),(985694,1085,1355236079),(985695,1085,1355236085),(985696,1085,1355236088),(985697,1085,1355236105),(985698,1085,1355236106),(985699,1085,1355236116),(985700,1085,1355236121),(985701,1085,1355236124),(985702,1085,1355236131),(985703,1085,1355236132),(985704,1085,1355236133),(985705,1085,1355236134),(985706,1085,1355236137),(985707,1085,1355236143),(985708,1085,1355236147),(985709,1085,1355236148),(985710,1085,1355236153),(985711,1085,1355236154),(985712,1085,1355236154),(985713,1085,1355236158),(985714,1085,1355236325),(985715,1085,1355236166),(985716,1085,1355236177),(985717,1085,1355236178),(985718,1085,1355236181),(985719,1085,1355236186),(985720,1085,1355236191),(985721,1085,1355236351),(985722,1085,1355236199),(985723,1085,1355242445),(985724,1085,1355236202),(985725,1085,1355236204),(985726,1085,1355236209),(985727,1085,1355236217),(985728,1085,1355236218),(985729,1085,1355236220),(985730,1085,1355236225),(985731,1085,1355236229),(985732,1046,1355236694),(985732,1085,1355236232),(985733,1085,1355236241),(985734,1085,1355236247),(985735,1085,1355236247),(985736,1085,1355236253),(985737,1085,1355236255),(985738,1085,1355236270),(985739,1085,1355236272),(985740,1085,1355236277),(985741,1085,1355236279),(985742,1085,1355236297),(985743,1085,1355236298),(985744,1085,1355236316),(985745,1085,1355236320),(985746,1085,1355236328),(985747,1085,1355236328),(985748,1085,1355236332),(985749,1085,1355236335),(985750,1085,1355236337),(985751,1085,1355236345),(985752,1085,1355236458),(985753,1085,1355236350),(985754,1085,1355236359),(985755,1085,1355236361),(985756,1085,1355236367),(985757,1085,1355236368),(985758,1085,1355236370),(985759,1085,1355236370),(985760,1085,1355323568),(985761,1085,1355236370),(985762,1085,1355236374),(985763,1085,1355236376),(985764,1085,1355236377),(985765,1085,1355236378),(985766,1085,1355236383),(985767,1085,1355236385),(985768,1085,1355236386),(985769,1085,1355236393),(985770,1085,1355236394),(985771,1085,1355236398),(985772,1085,1355236406),(985773,1085,1355236406),(985774,1045,1355237337),(985774,1085,1355236406),(985774,1227,1355237333),(985775,1045,1355236424),(985775,1085,1355236422),(985776,1085,1355236422),(985777,1085,1355236423),(985778,1085,1355236424),(985779,1085,1355236427),(985780,1085,1355236429),(985781,1085,1355236429),(985782,1085,1355236432),(985783,1085,1355236441),(985784,1085,1355236441),(985785,1085,1355236445),(985786,1085,1355236446),(985787,1085,1355236447),(985788,1085,1355236448),(985789,1085,1355236448),(985790,1085,1355236449),(985791,1085,1355236449),(985792,1085,1355236450),(985793,1085,1355236452),(985794,1085,1355236454),(985795,1085,1355236455),(985796,1085,1355236458),(985797,1085,1355236458),(985798,1085,1355237732),(985799,1085,1355236466),(985800,1085,1355236467),(985801,1085,1355236467),(985802,1085,1355236471),(985803,1085,1355236472),(985804,1085,1355242329),(985805,1046,1355816108),(985805,1085,1355236988),(985806,1085,1355236482),(985807,1085,1355236484),(985808,1085,1355236488),(985809,1085,1355236492),(985810,1085,1355270867),(985811,1085,1355236499),(985812,1085,1355236500),(985813,1085,1355236501),(985814,1085,1355236507),(985815,1085,1355236507),(985816,1085,1355236508),(985817,1085,1355236520),(985818,1085,1355236522),(985819,1085,1355236524),(985820,1085,1355236526),(985821,1085,1355236649),(985822,1085,1355236531),(985823,1085,1355236533),(985824,1085,1355236537),(985825,1085,1355236549),(985826,1085,1355236550),(985827,1085,1355236552),(985828,1085,1355236552),(985829,1085,1355236554),(985830,1085,1355236559),(985831,1085,1355236559),(985832,1085,1355236568),(985833,1085,1355236596),(985834,1085,1355236578),(985835,1085,1355236578),(985836,1085,1355236583),(985837,1085,1355236584),(985838,1085,1355236587),(985839,1085,1355236591),(985840,1085,1355236598),(985841,1085,1355236602),(985842,1085,1355236603),(985843,1085,1355236603),(985844,1085,1355236603),(985845,1045,1355510618),(985845,1085,1355236649),(985846,1085,1355236604),(985847,1085,1355236611),(985848,1085,1355236611),(985849,1085,1355236623),(985850,1085,1355236614),(985851,1085,1355236620),(985852,1085,1355236627),(985853,1085,1355236635),(985854,1085,1355236640),(985855,1085,1355236645),(985856,1085,1355236647),(985857,1085,1355236648),(985858,1085,1355236650),(985859,1085,1355236655),(985860,1085,1355236658),(985861,1085,1355236658),(985862,1085,1355236905),(985863,1085,1355236664),(985864,1045,1355237095),(985864,1085,1355236678),(985865,1085,1355236681),(985866,1085,1355236682),(985867,1085,1355236684),(985868,1085,1355236689),(985869,1085,1355236690),(985870,1085,1355236691),(985871,1085,1355236696),(985872,1085,1355236697),(985873,1085,1355236697),(985874,1085,1355236706),(985875,1085,1355236706),(985876,1085,1355236710),(985877,1085,1355236713),(985878,1085,1355236722),(985879,1085,1355236725),(985880,1085,1355236734),(985881,1085,1355236741),(985882,1085,1355236746),(985883,1085,1355236747),(985884,1085,1355236753),(985885,1085,1355236762),(985886,1085,1355236807),(985887,1085,1355236766),(985888,1085,1355236769),(985889,1085,1355236772),(985890,1085,1355236778),(985891,1085,1355236780),(985892,1085,1355236781),(985892,1236,1355236990),(985893,1085,1355236782),(985894,1085,1355236784),(985895,1085,1355236785),(985896,1045,1355238736),(985896,1085,1355236785),(985897,1085,1355236787),(985898,1085,1355236794),(985899,1085,1355236795),(985900,1085,1355236797),(985901,1085,1355236797),(985902,1085,1355236799),(985903,1085,1355236803),(985904,1085,1355236807),(985905,1085,1355236808),(985906,1085,1355236809),(985907,1085,1355236809),(985908,1085,1355236812),(985909,1085,1355252603),(985910,1085,1355236819),(985911,1085,1355236833),(985912,1085,1355236834),(985913,1085,1355236840),(985914,1085,1355236845),(985915,1085,1355236845),(985916,1085,1355236849),(985917,1085,1355237075),(985918,1085,1355236855),(985919,1045,1355237284),(985919,1085,1355236861),(985919,1227,1355237283),(985920,1085,1355236868),(985921,1085,1355236871),(985922,1085,1355236873),(985923,1085,1355236879),(985924,1085,1355236882),(985925,1085,1355236885),(985926,1085,1355236886),(985927,1085,1355236890),(985928,1085,1355236891),(985929,1085,1355236894),(985930,1085,1355236895),(985931,1085,1355236901),(985932,1085,1355236904),(985933,1085,1355236907),(985934,1085,1355236908),(985935,1085,1355236914),(985936,1085,1355236915),(985937,1085,1355236918),(985938,1085,1355236918),(985939,1085,1355236923),(985940,1085,1355236925),(985941,1085,1355236930),(985942,1085,1355236931),(985943,1085,1355236932),(985944,1085,1355236933),(985945,1085,1355236938),(985946,1085,1355236939),(985947,1085,1355236941),(985948,1085,1355236943),(985949,1085,1355236943),(985950,1085,1355236943),(985951,1085,1355236945),(985952,1085,1355236955),(985953,1046,1355812918),(985953,1085,1355236985),(985954,1085,1355236961),(985955,1085,1355237175),(985956,1085,1355236964),(985957,1085,1355236976),(985958,1085,1355236977),(985959,1085,1355236985),(985960,1085,1355236987),(985961,1085,1355236990),(985962,1085,1355236990),(985963,1085,1355236995),(985964,1085,1355236996),(985965,1085,1355237028),(985966,1085,1355237002),(985967,1085,1355237004),(985968,1085,1355237004),(985969,1085,1355237005),(985970,1085,1355237011),(985971,1085,1355237011),(985972,1085,1355237014),(985973,1085,1355237015),(985974,1085,1355237016),(985975,1085,1355237016),(985976,1085,1355237018),(985977,1085,1355237020),(985978,1085,1355237021),(985979,1085,1355237023),(985980,1085,1355237024),(985981,1085,1355237027),(985982,1085,1355237028),(985983,1085,1355237031),(985984,1085,1355237035),(985985,1085,1355237039),(985986,1085,1355237040),(985987,1085,1355237041),(985988,1085,1355237044),(985988,1236,1355237372),(985989,1085,1355237046),(985990,1085,1355237219),(985991,1085,1355237058),(985992,1085,1355237063),(985993,1085,1355237063),(985994,1085,1355237077),(985995,1085,1355237081),(985996,1085,1355237084),(985997,1085,1355237086),(985998,1085,1355237093),(985999,1085,1355237095),(986000,1085,1355237101),(986001,1085,1355237105),(986002,1085,1355237106),(986003,1085,1355237110),(986004,1085,1355237111),(986005,1085,1355237112),(986006,1085,1355237119),(986007,1085,1355237132),(986008,1085,1355237141),(986009,1085,1355237142),(986010,1085,1355237619),(986011,1085,1355237148),(986012,1085,1355237149),(986013,1085,1355237155),(986014,1085,1355237157),(986015,1085,1355237159),(986016,1085,1355238671),(986017,1085,1355237162),(986018,1085,1355237169),(986019,1085,1355237180),(986020,1085,1355237185),(986021,1085,1355237193),(986022,1085,1355237194),(986023,1085,1355237197),(986024,1085,1355237202),(986025,1085,1355237204),(986026,1085,1355237216),(986027,1085,1355237225),(986028,1085,1355237227),(986029,1085,1355237237),(986030,1085,1355237367),(986031,1085,1355237247),(986032,1085,1355237248),(986033,1085,1355237250),(986034,1085,1355237253),(986035,1085,1355237255),(986036,1085,1355237256),(986037,1085,1355237261),(986038,1085,1355237261),(986039,1085,1355237267),(986040,1085,1355237279),(986041,1085,1355237287),(986042,1085,1355237293),(986043,1085,1355237299),(986044,1085,1355237301),(986045,1085,1355237301),(986046,1085,1355237314),(986047,1085,1355237314),(986048,1085,1355237316),(986049,1085,1355237359),(986050,1045,1355237343),(986050,1085,1355237323),(986051,1085,1355237326),(986052,1085,1355237328),(986053,1085,1355237329),(986054,1085,1355237332),(986055,1085,1355237334),(986056,1085,1355237336),(986057,1085,1355237340),(986058,1085,1355237345),(986059,1085,1355237349),(986060,1085,1355237353),(986061,1085,1355237354),(986062,1085,1355237360),(986063,1085,1355237363),(986064,1085,1355237366),(986065,1085,1355237369),(986066,1085,1355237369),(986067,1085,1355237372),(986068,1085,1355237377),(986069,1085,1355237379),(986070,1085,1355237381),(986071,1085,1355237388),(986072,1085,1355237393),(986073,1085,1355237396),(986074,1085,1355237397),(986075,1085,1355237404),(986076,1085,1355237416),(986077,1085,1355237424),(986078,1085,1355237433),(986079,1085,1355237433),(986080,1085,1355237434),(986081,1085,1355237437),(986082,1045,1355237465),(986082,1085,1355237449),(986083,1085,1355237454),(986084,1085,1355237455),(986085,1085,1355237457),(986086,1085,1355237462),(986087,1085,1355237465),(986088,1085,1355237466),(986089,1085,1355237475),(986090,1085,1355237481),(986091,1085,1355237485),(986092,1085,1355237489),(986093,1085,1355237570),(986094,1085,1355237498),(986095,1085,1355237502),(986096,1085,1355237515),(986097,1085,1355237520),(986098,1085,1355237521),(986099,1085,1355237546),(986100,1085,1355237677),(986101,1085,1355237531),(986102,1085,1355237531),(986103,1085,1355237536),(986104,1085,1355237543),(986105,1085,1355237545),(986106,1085,1355237552),(986107,1085,1355237554),(986108,1085,1355237554),(986109,1085,1355237554),(986110,1085,1355237555),(986111,1085,1355237557),(986112,1085,1355237561),(986113,1085,1355237563),(986114,1085,1355237569),(986115,1085,1355237580),(986116,1085,1355237584),(986117,1085,1355237590),(986118,1085,1355237592),(986119,1085,1355237593),(986120,1085,1355238178),(986121,1085,1355237608),(986122,1085,1355237608),(986123,1085,1355237610),(986124,1085,1355237610),(986125,1085,1355237611),(986126,1085,1355237919),(986127,1045,1355237620),(986127,1085,1355237617),(986128,1085,1355237618),(986129,1085,1355237618),(986130,1085,1355237622),(986131,1045,1355238140),(986131,1085,1355237634),(986131,1227,1355238139),(986131,1236,1355238283),(986132,1085,1355237635),(986133,1085,1355237637),(986134,1085,1355237645),(986135,1085,1355237649),(986136,1085,1355237697),(986137,1085,1355237659),(986138,1085,1355237661),(986139,1085,1355237666),(986140,1085,1355237670),(986141,1085,1355237673),(986142,1085,1355237677),(986143,1085,1355237680),(986144,1085,1355237680),(986145,1085,1355237681),(986146,1085,1355237684),(986147,1085,1355237688),(986148,1085,1355237695),(986149,1085,1355237704),(986150,1085,1355237710),(986151,1085,1355237713),(986152,1085,1355237713),(986153,1085,1355237721),(986154,1085,1355238364),(986155,1085,1355237725),(986156,1085,1355237731),(986157,1085,1355237743),(986158,1085,1355237756),(986159,1085,1355237758),(986160,1085,1355237758),(986161,1085,1355237759),(986162,1085,1355237768),(986163,1085,1355237769),(986164,1085,1355237770),(986165,1085,1355237770),(986166,1085,1355237774),(986167,1085,1355237780),(986168,1085,1355237800),(986169,1085,1355237789),(986170,1085,1355237789),(986171,1085,1355237791),(986172,1085,1355237796),(986173,1085,1355237797),(986174,1085,1355237799),(986175,1085,1355237807),(986176,1085,1355237809),(986177,1085,1355237810),(986178,1085,1355237811),(986179,1085,1355237813),(986180,1085,1355237817),(986181,1085,1355237824),(986182,1085,1355237824),(986183,1085,1355237824),(986184,1085,1355238215),(986185,1085,1355237830),(986186,1085,1355237833),(986187,1085,1355237850),(986188,1085,1355237853),(986189,1085,1355237854),(986190,1085,1355237855),(986191,1085,1355237856),(986192,1085,1355237869),(986193,1085,1355237873),(986194,1085,1355237874),(986195,1085,1355244525),(986196,1085,1355237875),(986197,1085,1355237876),(986198,1085,1355237885),(986199,1085,1355238520),(986200,1085,1355237895),(986201,1085,1355237897),(986202,1085,1355237898),(986203,1085,1355237911),(986204,1085,1355237912),(986205,1085,1355269945),(986206,1085,1355237921),(986207,1085,1355237923),(986208,1085,1355237926),(986209,1085,1355237928),(986210,1085,1355237943),(986211,1085,1355237945),(986212,1085,1355237945),(986213,1085,1355237950),(986214,1085,1355237960),(986215,1085,1355237967),(986216,1085,1355237969),(986217,1045,1355237996),(986217,1085,1355237982),(986218,1085,1355237985),(986219,1085,1355237993),(986220,1085,1355238006),(986221,1085,1355238034),(986222,1085,1355238013),(986222,1236,1355238115),(986223,1085,1355238024),(986224,1085,1355238024),(986225,1085,1355238024),(986226,1085,1355238029),(986227,1085,1355238036),(986228,1045,1355248366),(986228,1085,1355238048),(986229,1085,1355238060),(986230,1085,1355238063),(986231,1085,1355238066),(986232,1085,1355238068),(986233,1085,1355238068),(986234,1085,1355238108),(986235,1085,1355238074),(986236,1085,1355238075),(986237,1085,1355238076),(986238,1085,1355238077),(986239,1085,1355238084),(986240,1085,1355238089),(986241,1085,1355238091),(986242,1085,1355238094),(986243,1085,1355238095),(986244,1085,1355238100),(986245,1085,1355238113),(986246,1045,1355238136),(986246,1085,1355238120),(986247,1085,1355238121),(986248,1085,1355238126),(986249,1085,1355238130),(986250,1085,1355238136),(986251,1085,1355238139),(986252,1085,1355238143),(986253,1085,1355238144),(986254,1085,1355238148),(986255,1085,1355238154),(986256,1085,1355238161),(986257,1085,1355238164),(986258,1085,1355238165),(986259,1085,1355238173),(986260,1085,1355238175),(986261,1085,1355238177),(986262,1085,1355238178),(986263,1085,1355238196),(986264,1085,1355238198),(986265,1085,1355238204),(986266,1085,1355238222),(986267,1085,1355238225),(986268,1085,1355238228),(986269,1085,1355238235),(986270,1085,1355238237),(986271,1085,1355238239),(986272,1085,1355238239),(986273,1085,1355238240),(986274,1085,1355238249),(986275,1045,1355238273),(986275,1085,1355238332),(986276,1085,1355238268),(986277,1085,1355238273),(986278,1085,1355238276),(986279,1085,1355238285),(986280,1085,1355238292),(986281,1085,1355238294),(986282,1085,1355238298),(986283,1085,1355238305),(986284,1085,1355238306),(986285,1085,1355238308),(986286,1085,1355238312),(986287,1085,1355238313),(986288,1085,1355238318),(986288,1236,1355238821),(986289,1085,1355238334),(986290,1085,1355238321),(986291,1085,1355238323),(986292,1085,1355238329),(986293,1085,1355238329),(986294,1085,1355238331),(986295,1085,1355238336),(986296,1085,1355238341),(986297,1085,1355238990),(986298,1085,1355238353),(986299,1085,1355238374),(986300,1085,1355238382),(986301,1085,1355238392),(986302,1085,1355238402),(986303,1085,1355238409),(986304,1085,1355238423),(986305,1085,1355238424),(986306,1085,1355238426),(986307,1085,1355238428),(986308,1085,1355238432),(986309,1085,1355238438),(986310,1085,1355238446),(986311,1085,1355238451),(986312,1085,1355238456),(986313,1085,1355238456),(986314,1085,1355238459),(986315,1085,1355238464),(986316,1085,1355238468),(986317,1085,1355238484),(986318,1085,1355238489),(986319,1085,1355238502),(986320,1085,1355238508),(986321,1085,1355238524),(986322,1085,1355238524),(986323,1085,1355238528),(986324,1085,1355238535),(986325,1085,1355238541),(986326,1085,1355238543),(986327,1085,1355238548),(986328,1085,1355238565),(986329,1085,1355238566),(986330,1085,1355238576),(986331,1085,1355238577),(986332,1085,1355238584),(986333,1085,1355238584),(986334,1085,1355238594),(986335,1085,1355238594),(986336,1085,1355238597),(986337,1085,1355238599),(986338,1085,1355238599),(986339,1085,1355238601),(986340,1085,1355238608),(986341,1085,1355238612),(986342,1085,1355238624),(986343,1085,1355278245),(986344,1085,1355238639),(986345,1085,1355238639),(986346,1085,1355238645),(986347,1085,1355238648),(986348,1085,1355238649),(986349,1085,1355238651),(986350,1085,1355238661),(986351,1085,1355238663),(986352,1085,1355238663),(986353,1085,1355238668),(986354,1085,1355238673),(986355,1085,1355238683),(986356,1085,1355238694),(986357,1085,1355238696),(986358,1085,1355238697),(986359,1085,1355238697),(986360,1085,1355238701),(986361,1085,1355238706),(986362,1085,1355238708),(986363,1085,1355238711),(986364,1085,1355238715),(986365,1085,1355238723),(986366,1085,1355238729),(986367,1085,1355238751),(986368,1085,1355238753),(986369,1085,1355238896),(986370,1085,1355238766),(986371,1085,1355238772),(986372,1085,1355238777),(986373,1085,1355238806),(986374,1085,1355238839),(986375,1085,1355238839),(986376,1085,1355238839),(986377,1085,1355238842),(986378,1085,1355238844),(986379,1085,1355238865),(986380,1085,1355239243),(986381,1085,1355238877),(986382,1085,1355238879),(986383,1085,1355238900),(986384,1085,1355238906),(986385,1085,1355238923),(986386,1085,1355238926),(986387,1085,1355238928),(986388,1085,1355238942),(986389,1085,1355238943),(986390,1085,1355238955),(986391,1085,1355239194),(986392,1085,1355238976),(986393,1085,1355238978),(986394,1085,1355238984),(986394,1236,1355239467),(986395,1085,1355238988),(986396,1085,1355238991),(986397,1085,1355238991),(986398,1085,1355238992),(986399,1085,1355238998),(986400,1085,1355239006),(986401,1085,1355239014),(986402,1085,1355239016),(986403,1085,1355239028),(986404,1085,1355239030),(986405,1085,1355239044),(986406,1085,1355239047),(986407,1085,1355239052),(986408,1085,1355239056),(986409,1085,1355239064),(986410,1085,1355239069),(986411,1085,1355239085),(986412,1085,1355239086),(986413,1085,1355239088),(986414,1046,1355839401),(986414,1085,1355239090),(986415,1085,1355239094),(986416,1085,1355239095),(986417,1085,1355239098),(986418,1085,1355239102),(986419,1085,1355239103),(986420,1085,1355239115),(986421,1085,1355239115),(986422,1085,1355239126),(986423,1085,1355239130),(986424,1085,1355239131),(986425,1085,1355239131),(986426,1085,1355239132),(986427,1085,1355239137),(986428,1085,1355239189),(986429,1085,1355239158),(986430,1085,1355239158),(986431,1085,1355239162),(986432,1085,1355239164),(986433,1085,1355239176),(986434,1085,1355239178),(986435,1085,1355239179),(986436,1085,1355239184),(986437,1085,1355329357),(986438,1085,1355239193),(986439,1085,1355239195),(986440,1085,1355239747),(986441,1085,1355239212),(986442,1085,1355239215),(986443,1085,1355239219),(986444,1085,1355239220),(986445,1085,1355239229),(986446,1085,1355239233),(986447,1085,1355239233),(986448,1085,1355239242),(986449,1085,1355239264),(986450,1085,1355239249),(986451,1085,1355239251),(986452,1085,1355239285),(986453,1085,1355239287),(986454,1085,1355239297),(986455,1085,1355239298),(986456,1085,1355239301),(986457,1085,1355239310),(986458,1085,1355239332),(986459,1085,1355239348),(986460,1085,1355239363),(986461,1085,1355239384),(986462,1085,1355239548),(986463,1085,1355239421),(986464,1085,1355239431),(986465,1085,1355239433),(986466,1085,1355239441),(986467,1085,1355239444),(986468,1085,1355239444),(986469,1085,1355239465),(986470,1085,1355239468),(986471,1085,1355239531),(986472,1085,1355239477),(986473,1085,1355239496),(986474,1085,1355239507),(986475,1085,1355239510),(986476,1085,1355239522),(986477,1085,1355239529),(986478,1085,1355239529),(986479,1085,1355239534),(986480,1085,1355239540),(986481,1085,1355239553),(986482,1085,1355239566),(986483,1085,1355239590),(986484,1085,1355239603),(986485,1085,1355239607),(986486,1085,1355239633),(986487,1085,1355239626),(986488,1085,1355239628),(986489,1085,1355239637),(986490,1085,1355239638),(986491,1085,1355239640),(986492,1085,1355239642),(986493,1085,1355239751),(986494,1085,1355239671),(986495,1085,1355239677),(986496,1085,1355239700),(986497,1085,1355239703),(986498,1085,1355239715),(986499,1085,1355239723),(986500,1085,1355239727),(986501,1085,1355239769),(986502,1085,1355239732),(986503,1085,1355239745),(986504,1085,1355239750),(986505,1085,1355239752),(986506,1085,1355239795),(986507,1085,1355239768),(986508,1085,1355239785),(986509,1085,1355239790),(986510,1085,1355239794),(986511,1085,1355239798),(986512,1085,1355239802),(986513,1085,1355239802),(986514,1085,1355239805),(986515,1085,1355239822),(986516,1085,1355239831),(986517,1085,1355239852),(986518,1085,1355239854),(986519,1085,1355239861),(986520,1085,1355239861),(986521,1085,1355239865),(986522,1085,1355239866),(986523,1085,1355239905),(986524,1085,1355239878),(986525,1085,1355239878),(986526,1085,1355239879),(986527,1085,1355246709),(986528,1085,1355239885),(986529,1045,1355239908),(986529,1085,1355239887),(986530,1085,1355239888),(986531,1085,1355239888),(986532,1045,1355239903),(986532,1085,1355239891),(986533,1085,1355239892),(986534,1085,1355239902),(986535,1085,1355239908),(986536,1085,1355239922),(986537,1085,1355239922),(986538,1085,1355239923),(986539,1085,1355239943),(986540,1085,1355239928),(986541,1085,1355239929),(986542,1085,1355239931),(986543,1085,1355239932),(986544,1085,1355239947),(986545,1085,1355239957),(986546,1045,1355240007),(986546,1085,1355239982),(986547,1085,1355239989),(986548,1085,1355239996),(986549,1085,1355240001),(986550,1085,1355240017),(986551,1085,1355240033),(986552,1085,1355240034),(986553,1085,1355240040),(986554,1085,1355240042),(986555,1085,1355240043),(986556,1085,1355240054),(986557,1085,1355242399),(986558,1085,1355240061),(986559,1085,1355240062),(986560,1085,1355240062),(986561,1085,1355240068),(986562,1085,1355240071),(986563,1085,1355240072),(986564,1085,1355240075),(986565,1085,1355240076),(986566,1085,1355240082),(986567,1085,1355240348),(986568,1085,1355240104),(986569,1085,1355240115),(986570,1085,1355240116),(986571,1085,1355240173),(986572,1085,1355240119),(986573,1085,1355240120),(986574,1085,1355240126),(986575,1046,1355814050),(986575,1085,1355240136),(986576,1085,1355240136),(986577,1085,1355240137),(986578,1085,1355240141),(986579,1085,1355240142),(986580,1085,1355240151),(986581,1085,1355240154),(986582,1085,1355240156),(986583,1085,1355240161),(986584,1085,1355240165),(986585,1085,1355240166),(986586,1085,1355240242),(986587,1085,1355240179),(986588,1085,1355240189),(986589,1085,1355240205),(986590,1085,1355240220),(986591,1085,1355240227),(986592,1085,1355240233),(986593,1085,1355240238),(986594,1045,1355346989),(986594,1085,1355240241),(986595,1085,1355240243),(986596,1085,1355240248),(986597,1085,1355240257),(986598,1085,1355240267),(986599,1085,1355240268),(986600,1085,1355240268),(986601,1085,1355240271),(986602,1085,1355240275),(986603,1085,1355240341),(986604,1085,1355240296),(986605,1085,1355240298),(986606,1085,1355240316),(986607,1085,1355240320),(986608,1085,1355240326),(986609,1085,1355240327),(986610,1085,1355240331),(986611,1085,1355240342),(986612,1085,1355240351),(986613,1085,1355240352),(986614,1085,1355240375),(986615,1085,1355240401),(986616,1085,1355240403),(986617,1085,1355240402),(986618,1085,1355240411),(986619,1085,1355240423),(986620,1085,1355240424),(986621,1085,1355240430),(986622,1085,1355240441),(986623,1085,1355240443),(986624,1085,1355240745),(986625,1085,1355240454),(986626,1085,1355240460),(986627,1085,1355240461),(986628,1085,1355240462),(986629,1085,1355240462),(986630,1085,1355240463),(986631,1085,1355240464),(986632,1085,1355240469),(986633,1085,1355240481),(986634,1085,1355240495),(986635,1085,1355240504),(986636,1085,1355240514),(986637,1085,1355240523),(986638,1085,1355240525),(986639,1085,1355240527),(986640,1085,1355240529),(986641,1085,1355240529),(986642,1085,1355240573),(986643,1085,1355240762),(986644,1085,1355240597),(986645,1085,1355240600),(986646,1085,1355240603),(986647,1085,1355240605),(986648,1085,1355240619),(986649,1085,1355240646),(986650,1085,1355240652),(986651,1085,1355240658),(986652,1085,1355240661),(986653,1085,1355240661),(986654,1085,1355240661),(986655,1085,1355240665),(986656,1085,1355240675),(986657,1085,1355240678),(986658,1085,1355240682),(986659,1085,1355240682),(986660,1085,1355240696),(986661,1085,1355240701),(986662,1085,1355240704),(986663,1085,1355240806),(986664,1085,1355240733),(986665,1085,1355240724),(986666,1085,1355240731),(986667,1085,1355240743),(986669,1085,1355240753),(986670,1085,1355240754),(986671,1085,1355240777),(986672,1085,1355240782),(986673,1085,1355240792),(986674,1085,1355240799),(986675,1085,1355240799),(986676,1085,1355240799),(986677,1085,1355240820),(986678,1085,1355240824),(986679,1085,1355240833),(986680,1085,1355240833),(986681,1085,1355240849),(986682,1085,1355240853),(986683,1085,1355240867),(986684,1085,1355240873),(986685,1085,1355240874),(986686,1085,1355240878),(986687,1085,1355240879),(986688,1085,1355240880),(986689,1085,1355240892),(986690,1085,1355240897),(986691,1085,1355240899),(986692,1085,1355240904),(986693,1085,1355240933),(986694,1085,1355240936),(986695,1085,1355240940),(986696,1085,1355240947),(986697,1085,1355240955),(986698,1085,1355429169),(986699,1085,1355240959),(986700,1085,1355240959),(986701,1085,1355240961),(986702,1085,1355240966),(986703,1085,1355240968),(986704,1085,1355240979),(986705,1085,1355240980),(986706,1085,1355241021),(986707,1085,1355241045),(986708,1085,1355241051),(986709,1085,1355241055),(986710,1085,1355241064),(986711,1085,1355241065),(986712,1085,1355241070),(986713,1085,1355241072),(986714,1085,1355241076),(986715,1085,1355241076),(986716,1085,1355241093),(986717,1085,1355241096),(986718,1085,1355241096),(986719,1085,1355241098),(986720,1085,1355241100),(986721,1085,1355241101),(986722,1085,1355241114),(986723,1085,1355241127),(986724,1085,1355241128),(986725,1085,1355241133),(986726,1085,1355241134),(986727,1085,1355241139),(986728,1085,1355241229),(986729,1085,1355241150),(986730,1085,1355241150),(986731,1085,1355241154),(986732,1085,1355280547),(986733,1085,1355241156),(986734,1085,1355241158),(986735,1085,1355241179),(986736,1085,1355241187),(986737,1085,1355241192),(986738,1085,1355241202),(986739,1085,1355241228),(986740,1085,1355241244),(986741,1085,1355241250),(986742,1085,1355241267),(986743,1085,1355241293),(986744,1085,1355241315),(986745,1085,1355241327),(986746,1085,1355241333),(986747,1085,1355241334),(986748,1085,1355241338),(986749,1085,1355241339),(986750,1085,1355241355),(986751,1085,1355241357),(986752,1085,1355241364),(986753,1085,1355241365),(986754,1085,1355241368),(986755,1045,1355848958),(986755,1085,1355241376),(986756,1085,1355241381),(986757,1085,1355249956),(986758,1085,1355241387),(986759,1085,1355241391),(986760,1085,1355241394),(986761,1085,1355241395),(986762,1085,1355241401),(986763,1085,1355241414),(986764,1085,1355241428),(986765,1085,1355241432),(986766,1085,1355241432),(986767,1085,1355241432),(986768,1085,1355241446),(986769,1085,1355241457),(986770,1085,1355241477),(986771,1085,1355241485),(986772,1085,1355241490),(986773,1085,1355241502),(986774,1085,1355241516),(986775,1085,1355241519),(986776,1085,1355241523),(986777,1085,1355241532),(986778,1085,1355241537),(986779,1085,1355275073),(986780,1085,1355241568),(986781,1085,1355241589),(986782,1085,1355241597),(986783,1085,1355241597),(986784,1085,1355241603),(986785,1085,1355241626),(986786,1085,1355241628),(986787,1085,1355241632),(986788,1085,1355241632),(986789,1085,1355241646),(986790,1085,1355241647),(986791,1085,1355241648),(986792,1085,1355241652),(986793,1085,1355241655),(986794,1085,1355241662),(986795,1085,1355241669),(986796,1085,1355241679),(986797,1085,1355241689),(986798,1085,1355241716),(986799,1085,1355241725),(986800,1085,1355241728),(986801,1085,1355241729),(986802,1085,1355241743),(986803,1085,1355241756),(986804,1085,1355241811),(986805,1085,1355241775),(986806,1085,1355241790),(986807,1085,1355241792),(986808,1085,1355241839),(986809,1085,1355242396),(986810,1085,1355241916),(986811,1085,1355241854),(986812,1085,1355241856),(986813,1085,1355241859),(986814,1085,1355241861),(986815,1085,1355241890),(986816,1085,1355241903),(986817,1085,1355241912),(986818,1085,1355241912),(986819,1085,1355241926),(986820,1085,1355241929),(986821,1085,1355241936),(986822,1085,1355241942),(986823,1085,1355241944),(986824,1085,1355241983),(986825,1085,1355241983),(986826,1085,1355242003),(986827,1085,1355242011),(986828,1085,1355242141),(986829,1085,1355242075),(986830,1085,1355242050),(986831,1085,1355242065),(986832,1085,1355242075),(986833,1085,1355242078),(986834,1085,1355242080),(986835,1085,1355242083),(986836,1085,1355242092),(986837,1085,1355242122),(986838,1085,1355242096),(986839,1085,1355242101),(986840,1085,1355242102),(986841,1085,1355242112),(986842,1085,1355242113),(986843,1085,1355242139),(986844,1085,1355242144),(986845,1085,1355242145),(986846,1085,1355242147),(986847,1085,1355242147),(986848,1085,1355242158),(986849,1085,1355242171),(986850,1085,1355242175),(986851,1085,1355242175),(986852,1085,1355242188),(986853,1085,1355242189),(986854,1085,1355242197),(986855,1085,1355242214),(986856,1085,1355242215),(986857,1085,1355242223),(986858,1085,1355242229),(986859,1085,1355242250),(986860,1085,1355242259),(986861,1085,1355242261),(986862,1085,1355242271),(986863,1085,1355242277),(986864,1085,1355242278),(986865,1085,1355242282),(986866,1085,1355242283),(986867,1085,1355242295),(986868,1085,1355242299),(986869,1085,1355242303),(986870,1045,1356046248),(986870,1085,1355242313),(986871,1085,1355242343),(986872,1085,1355242373),(986873,1085,1355242336),(986874,1085,1355242337),(986875,1085,1355242342),(986876,1085,1355242347),(986877,1085,1355242353),(986878,1085,1355242356),(986879,1085,1355242364),(986880,1085,1355242368),(986881,1085,1355242376),(986882,1085,1355242382),(986883,1085,1355242390),(986884,1085,1355242399),(986885,1085,1355242401),(986886,1085,1355242418),(986887,1085,1355242426),(986888,1085,1355242474),(986889,1085,1355242475),(986890,1085,1355242529),(986891,1085,1355242532),(986892,1085,1355242556),(986893,1085,1355242570),(986894,1045,1355242581),(986894,1085,1355242578),(986895,1085,1355242580),(986896,1085,1355242602),(986897,1085,1355242604),(986898,1085,1355242621),(986899,1085,1355242626),(986900,1085,1355242634),(986901,1085,1355242636),(986902,1085,1355242642),(986903,1085,1355242648),(986904,1085,1355242648),(986905,1085,1355242648),(986906,1085,1355242649),(986907,1085,1355242652),(986908,1085,1355242659),(986909,1085,1355242669),(986910,1085,1355242673),(986911,1085,1355242679),(986912,1085,1355242682),(986913,1085,1355242689),(986914,1085,1355242689),(986915,1085,1355242708),(986916,1085,1355242712),(986917,1085,1355242719),(986918,1085,1355242720),(986919,1085,1355242723),(986920,1085,1355242725),(986921,1085,1355242747),(986922,1045,1355242765),(986922,1085,1355242749),(986923,1085,1355242749),(986924,1085,1355242759),(986925,1085,1355242762),(986926,1085,1355242765),(986927,1085,1355242766),(986928,1085,1355242782),(986929,1085,1355242794),(986930,1085,1355242799),(986931,1085,1355242813),(986932,1085,1355242816),(986933,1085,1355242820),(986934,1085,1355242829),(986935,1085,1355242849),(986936,1085,1355242831),(986937,1085,1355242832),(986938,1085,1355242836),(986939,1085,1355242849),(986940,1085,1355242864),(986941,1085,1355242878),(986942,1085,1355242890),(986943,1085,1355242891),(986944,1085,1355242899),(986945,1085,1355243252),(986946,1085,1355243061),(986947,1085,1355242946),(986948,1085,1355242947),(986949,1085,1355242950),(986950,1085,1355242972),(986950,1236,1355243029),(986951,1085,1355242983),(986952,1085,1355242984),(986953,1085,1355243056),(986954,1085,1355243075),(986955,1085,1355243082),(986956,1085,1355243084),(986957,1085,1355243089),(986958,1085,1355243092),(986959,1085,1355243102),(986960,1085,1355243113),(986961,1085,1355243116),(986962,1085,1355243130),(986963,1085,1355243132),(986964,1085,1355243148),(986965,1085,1355243149),(986966,1085,1355243172),(986967,1085,1355243176),(986968,1085,1355243182),(986969,1085,1355243187),(986970,1085,1355243202),(986971,1085,1355243233),(986972,1085,1355243233),(986973,1085,1355243243),(986974,1085,1355243254),(986975,1085,1355243258),(986976,1085,1355243290),(986977,1085,1355243299),(986978,1085,1355243299),(986979,1085,1355243308),(986980,1085,1355243326),(986981,1085,1355243328),(986982,1085,1355243345),(986983,1085,1355243347),(986984,1085,1355243359),(986985,1085,1355243386),(986986,1085,1355243401),(986987,1085,1355243420),(986988,1085,1355243444),(986989,1085,1355243452),(986990,1085,1355243491),(986991,1085,1355243501),(986992,1085,1355243510),(986993,1085,1355243533),(986994,1085,1355243539),(986995,1085,1355243548),(986996,1085,1355243548),(986997,1085,1355243551),(986998,1085,1355243557),(986999,1085,1355243596),(987000,1085,1355243560),(987001,1085,1355243566),(987002,1085,1355243568),(987003,1085,1355243585),(987004,1085,1355243588),(987005,1085,1355243591),(987006,1085,1355243666),(987007,1085,1355243652),(987008,1085,1355243659),(987009,1085,1355243668),(987010,1085,1355243668),(987011,1085,1355243677),(987012,1085,1355243678),(987013,1085,1355243686),(987014,1085,1355243694),(987015,1085,1355243697),(987016,1085,1355243710),(987017,1085,1355243723),(987018,1085,1355243735),(987019,1085,1355243747),(987020,1085,1355243756),(987021,1085,1355243757),(987022,1085,1355243758),(987023,1085,1355243764),(987024,1085,1355243768),(987025,1085,1355243828),(987026,1085,1355243795),(987027,1085,1355244023),(987028,1085,1355243835),(987029,1085,1355243840),(987030,1085,1355243841),(987031,1085,1355243849),(987032,1085,1355243853),(987033,1085,1355243854),(987034,1085,1355243857),(987035,1085,1355249068),(987036,1085,1355243859),(987037,1085,1355243860),(987038,1085,1355243870),(987039,1085,1355243875),(987040,1085,1355243877),(987041,1085,1355243878),(987042,1085,1355243885),(987043,1085,1355243907),(987044,1085,1355243907),(987045,1085,1355243914),(987046,1085,1355243915),(987047,1085,1355243915),(987048,1085,1355244580),(987049,1085,1355243945),(987050,1085,1355243954),(987051,1085,1355243960),(987051,1236,1355244543),(987052,1085,1355386227),(987053,1085,1355243993),(987054,1085,1355243996),(987055,1085,1355244049),(987056,1085,1355244059),(987057,1085,1355244062),(987058,1085,1355244066),(987059,1085,1355244067),(987060,1085,1355244074),(987061,1085,1355244079),(987062,1085,1355244112),(987063,1085,1355244119),(987064,1085,1355244127),(987065,1085,1355244140),(987066,1085,1355244146),(987067,1085,1355244149),(987068,1085,1355244149),(987069,1085,1355244163),(987070,1085,1355244164),(987071,1085,1355244166),(987072,1085,1355244214),(987073,1085,1355244228),(987074,1085,1355244244),(987075,1085,1355244248),(987076,1085,1355244250),(987077,1085,1355244253),(987078,1085,1355244259),(987079,1085,1355244270),(987080,1085,1355244276),(987081,1085,1355244311),(987082,1085,1355244314),(987083,1085,1355244316),(987084,1085,1355244322),(987085,1085,1355244324),(987086,1085,1355244333),(987087,1085,1355244350),(987088,1085,1355244352),(987089,1085,1355244354),(987090,1085,1355244694),(987091,1085,1355244378),(987092,1085,1355244406),(987093,1085,1355244412),(987094,1085,1355244425),(987095,1085,1355244425),(987096,1085,1355244684),(987096,1236,1355244701),(987097,1085,1355244428),(987098,1085,1355244429),(987099,1085,1355244456),(987100,1085,1355244458),(987101,1085,1355244466),(987102,1085,1355244469),(987103,1085,1355244473),(987104,1085,1355244474),(987105,1085,1355244487),(987106,1085,1355244491),(987107,1085,1355244505),(987108,1085,1355244506),(987109,1085,1355244510),(987110,1085,1355244522),(987111,1085,1355244535),(987112,1085,1355244537),(987113,1085,1355244551),(987114,1085,1355244552),(987115,1085,1355244553),(987116,1085,1355244566),(987117,1085,1355244588),(987118,1085,1355244590),(987119,1085,1355244624),(987120,1085,1355244634),(987121,1085,1355244640),(987122,1085,1355244641),(987123,1085,1355244642),(987124,1085,1355244675),(987125,1085,1355244692),(987126,1085,1355244714),(987127,1085,1355244714),(987128,1085,1355244717),(987129,1046,1355244817),(987130,1085,1355244738),(987131,1085,1355244745),(987132,1085,1355244771),(987133,1085,1355244808),(987134,1085,1355244820),(987135,1085,1355244820),(987136,1085,1355244832),(987137,1085,1355244862),(987138,1085,1355244871),(987139,1045,1355244889),(987139,1085,1355244886),(987140,1085,1355244890),(987141,1085,1355244895),(987142,1085,1355244908),(987143,1085,1355244915),(987144,1085,1355244932),(987145,1085,1355244952),(987146,1085,1355244960),(987147,1085,1355244981),(987148,1085,1355244985),(987149,1085,1355244994),(987150,1085,1355244996),(987151,1085,1355245021),(987152,1085,1355245007),(987153,1085,1355245008),(987154,1085,1355416988),(987155,1085,1355245022),(987156,1085,1355245030),(987157,1085,1355245045),(987158,1085,1355245071),(987159,1085,1355245090),(987160,1085,1355245096),(987161,1085,1355245239),(987162,1085,1355245151),(987163,1085,1355245161),(987164,1085,1355262928),(987165,1085,1355245163),(987166,1085,1355245184),(987167,1085,1355245172),(987168,1085,1355245181),(987169,1085,1355245204),(987170,1085,1355245189),(987171,1085,1355245198),(987172,1085,1355245206),(987173,1085,1355245207),(987174,1085,1355245211),(987175,1085,1355245211),(987176,1085,1355245215),(987177,1085,1355245221),(987178,1085,1355245225),(987179,1046,1358021435),(987179,1085,1355245224),(987180,1085,1355245235),(987181,1085,1355245240),(987182,1085,1355245408),(987183,1045,1355245444),(987183,1085,1355245248),(987184,1085,1355245253),(987185,1085,1355245291),(987186,1085,1355245337),(987187,1085,1355245342),(987188,1085,1355245347),(987189,1085,1355245387),(987190,1085,1355245387),(987191,1085,1355245393),(987192,1085,1355245395),(987193,1085,1355245401),(987194,1085,1355245417),(987195,1085,1355245436),(987196,1085,1355245438),(987197,1085,1355245443),(987198,1085,1355299002),(987198,1236,1355808547),(987199,1085,1355245506),(987200,1085,1355245507),(987201,1085,1355245509),(987202,1085,1355245580),(987203,1085,1355245515),(987204,1085,1355245523),(987205,1085,1355245535),(987206,1085,1355245549),(987207,1085,1355245565),(987208,1085,1355245567),(987209,1085,1355245584),(987210,1085,1355245592),(987211,1085,1355245593),(987212,1045,1355245616),(987212,1085,1355245597),(987213,1085,1355245598),(987214,1085,1355245612),(987215,1085,1355245620),(987216,1085,1355245655),(987217,1085,1355245787),(987218,1085,1355245680),(987219,1085,1355245689),(987220,1085,1355245693),(987221,1085,1355245694),(987222,1085,1355245695),(987223,1085,1355245795),(987224,1085,1355245722),(987225,1085,1355245735),(987226,1085,1355245738),(987227,1085,1355245752),(987228,1085,1355245766),(987229,1045,1355245804),(987229,1085,1355245801),(987230,1085,1355245852),(987231,1085,1355245875),(987232,1085,1355245882),(987233,1085,1355246112),(987234,1085,1355245891),(987235,1085,1355245917),(987236,1085,1355245929),(987237,1085,1355245949),(987238,1085,1355245952),(987239,1085,1355245978),(987240,1085,1355245983),(987241,1085,1355245986),(987242,1085,1355246004),(987243,1085,1355246014),(987244,1085,1355246014),(987245,1085,1355246038),(987246,1085,1355246045),(987247,1085,1355246068),(987248,1085,1355246073),(987249,1045,1355349266),(987249,1085,1355246087),(987250,1085,1355246089),(987251,1085,1355246124),(987252,1085,1355246153),(987253,1085,1355246156),(987254,1085,1355246178),(987255,1085,1355246188),(987256,1085,1355246250),(987257,1085,1355246201),(987258,1085,1355246208),(987259,1085,1355246217),(987260,1085,1355246240),(987261,1085,1355246244),(987262,1085,1355246246),(987263,1085,1355246262),(987264,1085,1355246263),(987265,1085,1355246268),(987266,1085,1355246295),(987267,1085,1355246312),(987268,1085,1355246322),(987269,1085,1355246328),(987270,1042,1357336845),(987270,1046,1357336847),(987270,1085,1355246336),(987271,1085,1355246346),(987272,1085,1355246349),(987273,1085,1355246352),(987274,1085,1355246353),(987275,1085,1355246361),(987276,1085,1355246366),(987277,1085,1355246403),(987278,1085,1355246403),(987279,1085,1355246429),(987280,1085,1355246432),(987281,1085,1355246438),(987282,1085,1355246457),(987283,1085,1355246482),(987284,1085,1355246488),(987285,1085,1355246537),(987286,1085,1355246510),(987287,1085,1355246524),(987288,1085,1355246527),(987289,1085,1355246564),(987290,1085,1355246567),(987291,1085,1355246574),(987292,1085,1355246580),(987293,1085,1355246582),(987294,1085,1355246585),(987295,1085,1355246602),(987296,1085,1355246615),(987297,1085,1355246617),(987298,1085,1355246625),(987299,1085,1355246640),(987300,1085,1355246644),(987301,1085,1355247038),(987302,1085,1355246725),(987303,1085,1355246727),(987304,1085,1355246750),(987305,1085,1355246758),(987306,1085,1355246776),(987307,1045,1355246795),(987308,1085,1355246796),(987309,1085,1355246812),(987310,1085,1355246824),(987311,1085,1355246826),(987312,1085,1355246842),(987313,1085,1355246849),(987314,1085,1355246867),(987315,1085,1355246875),(987316,1085,1355246880),(987317,1085,1355246906),(987318,1085,1355246908),(987319,1085,1355246936),(987320,1085,1355246940),(987321,1085,1355246944),(987322,1085,1355246977),(987323,1085,1355246992),(987324,1085,1355247002),(987325,1085,1355247025),(987326,1085,1355247047),(987327,1085,1355247063),(987328,1085,1355247104),(987329,1085,1355247107),(987330,1085,1355247117),(987331,1085,1355247123),(987332,1085,1355247126),(987333,1085,1355247167),(987334,1085,1355247185),(987335,1085,1355247187),(987336,1085,1355247188),(987337,1085,1355247211),(987338,1085,1355247216),(987339,1085,1355247216),(987340,1085,1355247219),(987341,1085,1355247220),(987342,1085,1355247227),(987343,1085,1355247246),(987344,1085,1355247357),(987345,1085,1355247281),(987346,1085,1355247283),(987347,1085,1355247319),(987348,1085,1355247329),(987349,1085,1355247329),(987350,1085,1355247330),(987351,1046,1355884420),(987351,1085,1355247336),(987352,1085,1355247342),(987353,1085,1355247350),(987354,1085,1355247361),(987355,1085,1355247370),(987356,1085,1355247381),(987357,1085,1355247614),(987358,1085,1355247393),(987359,1085,1355247403),(987360,1085,1355247412),(987361,1085,1355247427),(987362,1085,1355247562),(987363,1085,1355247527),(987364,1085,1355247481),(987365,1085,1355247487),(987366,1085,1355247489),(987367,1085,1355247532),(987368,1085,1355247545),(987369,1085,1355247553),(987370,1085,1355247586),(987371,1085,1355247588),(987372,1085,1355247635),(987373,1085,1355247647),(987374,1085,1355247650),(987375,1085,1355247658),(987376,1045,1355848603),(987376,1085,1355247661),(987377,1085,1355247670),(987378,1085,1355247681),(987379,1085,1355247681),(987380,1085,1355247700),(987381,1085,1355247715),(987382,1085,1355247718),(987383,1085,1355247721),(987384,1085,1355247740),(987385,1085,1355247775),(987386,1085,1355247789),(987387,1085,1355247802),(987388,1085,1355247804),(987389,1085,1355247806),(987390,1085,1355247808),(987391,1085,1355247852),(987392,1085,1355247869),(987393,1085,1355247885),(987394,1085,1355247889),(987395,1085,1355247905),(987396,1085,1355247925),(987397,1085,1355247930),(987398,1085,1355247938),(987399,1085,1355247950),(987400,1085,1355247951),(987401,1085,1355247976),(987402,1085,1355247995),(987403,1085,1355247996),(987404,1085,1355248015),(987405,1085,1355248024),(987406,1085,1355248062),(987407,1085,1355248068),(987408,1085,1355248070),(987409,1085,1355248091),(987410,1085,1355248092),(987411,1085,1355248741),(987412,1085,1355248170),(987413,1085,1355248171),(987414,1085,1355248240),(987415,1045,1357328056),(987415,1085,1355248221),(987415,1236,1357328793),(987416,1085,1355248230),(987417,1085,1355248233),(987418,1085,1355248260),(987419,1085,1355248262),(987420,1085,1355248288),(987421,1085,1355248304),(987422,1085,1355248322),(987423,1085,1355248327),(987424,1085,1355248341),(987425,1085,1355248347),(987426,1085,1355248418),(987427,1085,1355248361),(987428,1085,1355248380),(987429,1085,1355248382),(987430,1085,1355248386),(987431,1085,1355248685),(987432,1085,1355248421),(987433,1085,1355248422),(987434,1085,1355250297),(987435,1085,1355248441),(987436,1085,1355248447),(987437,1085,1355248550),(987438,1085,1355248480),(987439,1085,1355248520),(987440,1085,1355248520),(987441,1085,1355248520),(987442,1085,1355248534),(987443,1085,1355248535),(987444,1085,1355248536),(987445,1085,1355248540),(987446,1085,1355248552),(987447,1085,1355248583),(987448,1085,1355248595),(987449,1085,1355248599),(987450,1085,1355248608),(987451,1085,1355248662),(987452,1085,1355248674),(987453,1085,1355248685),(987454,1085,1355248692),(987455,1085,1355248710),(987456,1085,1355248720),(987457,1085,1355248721),(987458,1085,1355248723),(987459,1085,1355248727),(987460,1085,1355248757),(987461,1085,1355248786),(987462,1085,1355248797),(987463,1045,1355248821),(987463,1085,1355248807),(987464,1085,1355248814),(987465,1085,1355248833),(987466,1085,1355248869),(987467,1085,1355248891),(987467,1236,1355248956),(987468,1085,1355248913),(987469,1085,1355248940),(987470,1085,1355248960),(987470,1236,1355534772),(987471,1085,1355248965),(987472,1085,1355248972),(987473,1085,1355248989),(987474,1085,1355249009),(987475,1085,1355249012),(987476,1085,1355249032),(987477,1085,1355249070),(987478,1085,1355249089),(987479,1085,1355249092),(987480,1085,1355249125),(987481,1085,1355249126),(987482,1085,1355249127),(987483,1085,1355249127),(987484,1085,1355249141),(987485,1085,1355249160),(987486,1085,1355249183),(987487,1085,1355249215),(987488,1085,1355249308),(987489,1085,1355249235),(987490,1085,1355249241),(987491,1085,1355249256),(987492,1085,1355249268),(987493,1085,1355249290),(987494,1085,1355249294),(987495,1085,1355250153),(987496,1085,1355249299),(987497,1085,1355249306),(987498,1085,1355249313),(987499,1085,1355249365),(987500,1085,1355249387),(987500,1236,1355249529),(987501,1085,1355249390),(987502,1085,1355249392),(987503,1085,1355249405),(987504,1085,1355249409),(987505,1085,1355249428),(987506,1085,1355249438),(987507,1085,1355249449),(987508,1085,1355249458),(987509,1085,1355249466),(987510,1085,1355249540),(987511,1085,1355249610),(987512,1085,1355249625),(987513,1085,1355249643),(987514,1085,1355249691),(987515,1085,1355249691),(987516,1085,1355249695),(987517,1045,1355250721),(987517,1085,1355249731),(987518,1085,1355249713),(987519,1085,1355249740),(987520,1085,1355249740),(987521,1085,1355249753),(987522,1085,1355249791),(987523,1085,1355249794),(987524,1085,1355249821),(987525,1085,1355249822),(987526,1085,1355249823),(987527,1085,1355249842),(987528,1085,1355249878),(987529,1085,1355249893),(987530,1085,1355249900),(987531,1085,1355249902),(987532,1085,1355249972),(987533,1085,1355249972),(987534,1085,1355250039),(987535,1085,1355250052),(987536,1085,1355250072),(987537,1085,1355250094),(987538,1085,1355250144),(987539,1085,1355250260),(987540,1085,1355250191),(987541,1085,1355250169),(987542,1085,1355250186),(987543,1085,1355250189),(987544,1085,1355250193),(987545,1085,1355250199),(987546,1085,1355250202),(987547,1085,1355250206),(987548,1085,1355250213),(987549,1085,1355250215),(987550,1085,1355250216),(987551,1085,1355250216),(987552,1085,1355250224),(987553,1085,1355250248),(987554,1085,1355250288),(987555,1085,1355250298),(987556,1085,1355250309),(987557,1085,1355250331),(987558,1085,1355250338),(987559,1085,1355250463),(987560,1085,1355250352),(987561,1085,1355250372),(987562,1085,1355250389),(987563,1085,1355250394),(987564,1085,1355250404),(987565,1085,1355250407),(987566,1085,1355250407),(987567,1085,1355250413),(987568,1085,1355250415),(987569,1085,1355250425),(987570,1085,1355250440),(987571,1085,1355250461),(987572,1085,1355250487),(987573,1085,1355250496),(987574,1085,1355250522),(987575,1085,1355250527),(987576,1085,1355250529),(987577,1085,1355250560),(987578,1085,1355250565),(987579,1085,1355250568),(987580,1085,1355250585),(987581,1085,1355250617),(987582,1085,1355250641),(987583,1045,1355266782),(987583,1085,1355250643),(987584,1085,1355250645),(987585,1085,1355250655),(987586,1085,1355250655),(987587,1085,1355250660),(987588,1085,1355250676),(987589,1085,1355250676),(987590,1085,1355250679),(987591,1085,1355250685),(987592,1085,1355250733),(987593,1085,1355250736),(987594,1085,1355250748),(987595,1085,1355250785),(987596,1085,1355250790),(987597,1085,1355250799),(987598,1085,1355250808),(987599,1085,1355250813),(987600,1085,1355250819),(987601,1085,1355250822),(987602,1085,1355250829),(987603,1085,1355250830),(987604,1085,1355250876),(987605,1085,1355250897),(987606,1085,1355250916),(987607,1085,1355250926),(987608,1085,1355250963),(987609,1085,1355250975),(987610,1085,1355250983),(987611,1085,1355251010),(987612,1085,1355251012),(987613,1085,1355251074),(987614,1085,1355251084),(987615,1085,1355251125),(987616,1085,1355251125),(987617,1085,1355251140),(987618,1085,1355251144),(987619,1085,1355251167),(987620,1085,1355251170),(987621,1085,1355251192),(987622,1085,1355251197),(987623,1085,1355251292),(987624,1085,1355251216),(987625,1085,1355251201),(987626,1085,1355251221),(987627,1085,1355251222),(987628,1085,1355251223),(987629,1085,1355251248),(987630,1085,1355251257),(987631,1085,1355251386),(987632,1085,1355251324),(987633,1046,1355251432),(987633,1085,1355251336),(987634,1085,1355251358),(987635,1085,1355251364),(987636,1085,1355251418),(987637,1085,1355251431),(987638,1085,1355251434),(987639,1085,1355251446),(987640,1085,1355251494),(987641,1085,1355251511),(987642,1085,1355251511),(987643,1085,1355251515),(987644,1085,1355251526),(987645,1085,1355251536),(987646,1085,1355251539),(987647,1085,1355251627),(987648,1085,1355251629),(987649,1085,1355251632),(987650,1085,1355251667),(987651,1085,1355251670),(987652,1085,1355251671),(987653,1085,1355251696),(987654,1085,1355251736),(987655,1085,1355251757),(987656,1085,1355251783),(987657,1085,1355251790),(987658,1085,1355251819),(987659,1085,1355251845),(987660,1045,1355251907),(987660,1085,1355251858),(987661,1085,1355251864),(987662,1085,1355251868),(987663,1085,1355251916),(987664,1085,1355251927),(987665,1085,1355251951),(987666,1085,1355251981),(987667,1085,1355251984),(987668,1085,1355252001),(987669,1085,1355252004),(987670,1085,1355252005),(987671,1085,1355252005),(987672,1085,1355252017),(987673,1085,1355252026),(987674,1085,1355252039),(987675,1085,1355252042),(987676,1085,1355252050),(987677,1085,1355252077),(987678,1085,1355252149),(987679,1085,1355252171),(987680,1085,1355252179),(987681,1085,1355252190),(987682,1085,1355252191),(987683,1085,1355252220),(987684,1085,1355252233),(987685,1085,1355252258),(987686,1085,1355252298),(987687,1085,1355252352),(987688,1085,1355252382),(987689,1085,1355252419),(987690,1085,1355252443),(987691,1085,1355252446),(987692,1085,1355252477),(987693,1085,1355252477),(987694,1085,1355252490),(987695,1085,1355252491),(987696,1085,1355252495),(987697,1085,1355252507),(987698,1085,1355252511),(987699,1085,1355252515),(987700,1085,1355252554),(987701,1085,1355252539),(987702,1085,1355252545),(987703,1085,1355252545),(987704,1085,1355252575),(987705,1085,1355252591),(987706,1085,1355252592),(987707,1085,1355252640),(987708,1085,1355253380),(987709,1085,1355252662),(987710,1085,1355252708),(987711,1085,1355252715),(987712,1085,1355252809),(987713,1085,1355252766),(987714,1085,1355252778),(987715,1085,1355252850),(987716,1085,1355252908),(987717,1085,1355252914),(987718,1085,1355252924),(987719,1085,1355252961),(987720,1085,1355253065),(987721,1085,1355253012),(987722,1085,1355253013),(987723,1085,1355253013),(987724,1085,1355253021),(987725,1085,1355253049),(987726,1085,1355253050),(987727,1085,1355253054),(987728,1085,1355253065),(987729,1085,1355253096),(987730,1085,1355253120),(987731,1085,1355253131),(987732,1085,1355253162),(987733,1085,1355253197),(987734,1085,1355253214),(987735,1085,1355253236),(987736,1085,1355253236),(987737,1085,1355253237),(987738,1085,1355253258),(987739,1085,1355253260),(987740,1085,1355253308),(987741,1085,1355253325),(987742,1085,1355253326),(987743,1085,1355253352),(987744,1085,1355253390),(987745,1085,1355253465),(987746,1085,1355253495),(987747,1085,1355253507),(987748,1085,1355253542),(987749,1085,1355253616),(987750,1085,1355253617),(987751,1085,1355253619),(987752,1085,1355253619),(987753,1085,1355253623),(987754,1085,1355253624),(987755,1085,1355254023),(987756,1085,1355253682),(987757,1085,1355253741),(987758,1085,1355253753),(987759,1085,1355253774),(987760,1085,1355253807),(987761,1085,1355253817),(987762,1085,1355253834),(987763,1085,1355253947),(987764,1085,1355253959),(987765,1085,1355253964),(987766,1085,1355253993),(987767,1085,1355254036),(987768,1085,1355254050),(987769,1085,1355254059),(987770,1085,1355254084),(987771,1085,1355254099),(987772,1085,1355254139),(987773,1085,1355254767),(987774,1085,1355254190),(987775,1085,1355254239),(987776,1085,1355254242),(987777,1085,1355254270),(987778,1085,1355254321),(987779,1085,1355254339),(987780,1085,1355254684),(987781,1085,1355254436),(987782,1085,1355254437),(987783,1045,1355254463),(987783,1085,1355254455),(987784,1085,1355254521),(987785,1085,1355254545),(987786,1085,1355254548),(987787,1085,1355254587),(987788,1085,1355254590),(987789,1085,1355254597),(987790,1085,1355254683),(987791,1085,1355254685),(987792,1085,1355254714),(987793,1085,1355254740),(987794,1085,1355254772),(987795,1085,1355254792),(987796,1085,1355254796),(987797,1085,1355254796),(987798,1085,1355254797),(987799,1085,1355254799),(987800,1085,1355254832),(987801,1085,1355254838),(987802,1085,1355254841),(987803,1085,1355254857),(987804,1085,1355254858),(987805,1085,1355254916),(987806,1085,1355254925),(987806,1236,1355255075),(987807,1045,1355350558),(987807,1085,1355254984),(987808,1085,1355255036),(987809,1085,1355255064),(987810,1085,1355255093),(987811,1085,1355255095),(987812,1085,1355255120),(987813,1085,1355255140),(987814,1085,1355255182),(987815,1085,1355255186),(987816,1085,1355255194),(987817,1085,1355255215),(987818,1085,1355255257),(987819,1085,1355255287),(987820,1085,1355255336),(987821,1085,1355425057),(987822,1085,1355255415),(987823,1085,1355255591),(987824,1085,1355255437),(987825,1085,1355255462),(987826,1085,1355255493),(987827,1085,1355255496),(987828,1085,1355255533),(987829,1085,1355255563),(987830,1085,1355322487),(987831,1085,1355255608),(987832,1085,1355255622),(987833,1085,1355255641),(987834,1085,1355255641),(987835,1085,1355255657),(987836,1085,1355255696),(987837,1085,1355255701),(987838,1085,1355255702),(987839,1085,1355255719),(987840,1085,1355255759),(987841,1085,1355255916),(987842,1085,1355255928),(987843,1085,1355255930),(987844,1085,1355255941),(987845,1085,1355255981),(987846,1085,1355256038),(987847,1085,1355256039),(987848,1085,1355256059),(987849,1085,1355256109),(987850,1085,1355256112),(987851,1085,1355256113),(987852,1085,1355256238),(987853,1085,1355256131),(987854,1085,1355256139),(987855,1085,1355256158),(987856,1085,1355256199),(987857,1085,1355256275),(987858,1085,1355256276),(987859,1085,1355256368),(987860,1085,1355256378),(987861,1085,1355256384),(987862,1085,1355256446),(987863,1085,1355256457),(987864,1085,1355256493),(987865,1085,1355256497),(987866,1085,1355256507),(987867,1085,1355256512),(987868,1085,1355256549),(987869,1085,1355256571),(987870,1085,1355256597),(987871,1085,1355256606),(987872,1085,1355256647),(987873,1085,1355256657),(987874,1085,1355256675),(987875,1085,1355256713),(987876,1085,1355256717),(987877,1085,1355256733),(987878,1085,1355256760),(987879,1085,1355256838),(987880,1085,1355256772),(987881,1085,1355256788),(987882,1085,1355258041),(987883,1085,1355256819),(987884,1085,1355256836),(987885,1085,1355256865),(987886,1085,1355256891),(987887,1085,1355256901),(987888,1085,1355256909),(987889,1085,1355256963),(987890,1085,1355256994),(987891,1085,1355257058),(987892,1085,1355257109),(987893,1085,1355257136),(987894,1085,1355257155),(987895,1085,1355257159),(987896,1085,1355258080),(987897,1085,1355257247),(987898,1085,1355257274),(987899,1085,1355257322),(987900,1085,1355257351),(987901,1085,1355257360),(987902,1085,1355257378),(987903,1085,1355257381),(987904,1085,1355257417),(987905,1085,1355257441),(987906,1085,1355257448),(987907,1085,1355257454),(987908,1085,1355257483),(987909,1085,1355257522),(987910,1085,1355257562),(987911,1085,1355257562),(987912,1085,1355257564),(987913,1085,1355257611),(987914,1085,1355257638),(987915,1085,1355257663),(987916,1085,1355257685),(987917,1085,1355257746),(987918,1085,1355257798),(987919,1085,1355257799),(987920,1085,1355257804),(987921,1085,1355257847),(987922,1085,1355257862),(987923,1085,1355257878),(987924,1085,1355257898),(987925,1085,1355257912),(987926,1085,1355257948),(987927,1085,1355257960),(987928,1085,1355257971),(987929,1085,1355257982),(987930,1085,1355258020),(987931,1085,1355258066),(987932,1085,1355258085),(987933,1085,1355258086),(987934,1085,1355258122),(987935,1085,1355258124),(987936,1085,1355258147),(987937,1085,1355258194),(987938,1085,1355258206),(987939,1085,1355258218),(987940,1085,1355258226),(987941,1085,1355258274),(987942,1085,1355258311),(987943,1085,1355258325),(987944,1085,1355258325),(987945,1085,1355258335),(987946,1085,1355258348),(987947,1085,1355258385),(987948,1085,1355258403),(987949,1085,1355258426),(987950,1085,1355258455),(987951,1085,1355258499),(987952,1085,1355258512),(987953,1085,1355258514),(987954,1085,1355258523),(987955,1085,1355258537),(987956,1085,1355258541),(987957,1085,1355258559),(987958,1085,1355258602),(987959,1085,1355258609),(987960,1085,1355258647),(987961,1085,1355258669),(987962,1085,1355258704),(987963,1085,1355258732),(987964,1085,1355258756),(987965,1085,1355258788),(987966,1085,1355258797),(987967,1085,1355258800),(987968,1085,1355258803),(987969,1085,1355258825),(987970,1085,1355258826),(987971,1085,1355258852),(987972,1085,1355258870),(987973,1045,1355259203),(987973,1085,1355258884),(987974,1085,1355258909),(987975,1085,1355258932),(987976,1046,1355857520),(987976,1085,1355258933),(987977,1085,1355258987),(987978,1085,1355259018),(987979,1085,1355259022),(987980,1085,1355259251),(987981,1085,1355259061),(987982,1085,1355259121),(987983,1085,1355259127),(987984,1085,1355259128),(987985,1085,1355259132),(987986,1085,1355259183),(987987,1085,1355259263),(987988,1085,1355259267),(987989,1085,1355259268),(987990,1085,1355259271),(987991,1085,1355259321),(987992,1085,1355259444),(987993,1085,1355259361),(987994,1085,1355259393),(987995,1085,1355259401),(987996,1085,1355259428),(987997,1085,1355259444),(987998,1085,1355259459),(987999,1085,1355259466),(988000,1085,1355259479),(988001,1085,1355259483),(988002,1085,1355259493),(988003,1085,1355259497),(988004,1085,1355259498),(988005,1085,1355259502),(988006,1085,1355259511),(988007,1085,1355259531),(988008,1085,1355259564),(988009,1085,1355259623),(988010,1085,1355259624),(988011,1085,1355259641),(988012,1085,1355259646),(988013,1085,1355259653),(988014,1046,1355819605),(988014,1085,1355259661),(988015,1085,1355259693),(988016,1085,1355259731),(988017,1085,1355259741),(988018,1085,1355259745),(988019,1085,1355259774),(988020,1085,1355259807),(988021,1085,1355259856),(988022,1085,1355259926),(988023,1085,1355259966),(988024,1085,1355259994),(988025,1085,1355260007),(988026,1085,1355260016),(988027,1085,1355260019),(988028,1085,1355260059),(988029,1085,1355260071),(988030,1085,1355260108),(988031,1085,1355260119),(988032,1085,1355260145),(988033,1085,1355260151),(988034,1085,1355260160),(988035,1085,1355260172),(988036,1085,1355260186),(988037,1085,1355453278),(988038,1085,1355260295),(988039,1085,1355260307),(988040,1085,1355260461),(988041,1085,1355260472),(988042,1085,1355260510),(988043,1085,1355260530),(988044,1085,1355260611),(988045,1085,1355260634),(988046,1085,1355260660),(988047,1085,1355260666),(988048,1085,1355260749),(988049,1085,1355260783),(988050,1085,1355260794),(988051,1085,1355260821),(988052,1085,1355260866),(988053,1085,1355260951),(988054,1085,1355260951),(988055,1085,1355260953),(988056,1085,1355260958),(988057,1085,1355260974),(988058,1085,1355261036),(988059,1085,1355261064),(988060,1085,1355261102),(988061,1085,1355261129),(988062,1085,1355261148),(988063,1085,1355261160),(988064,1085,1355261179),(988065,1085,1355261187),(988066,1085,1355261200),(988067,1085,1355261216),(988068,1085,1355261249),(988069,1085,1355261255),(988070,1085,1355261290),(988071,1085,1355261299),(988072,1085,1355261332),(988074,1085,1355261397),(988075,1085,1355261401),(988075,1236,1355261938),(988076,1085,1355261448),(988077,1085,1355261424),(988078,1085,1355261436),(988079,1085,1355261520),(988080,1085,1355261535),(988081,1085,1355261548),(988082,1085,1355261700),(988083,1085,1355261758),(988084,1085,1355261767),(988085,1085,1355261774),(988086,1085,1355261834),(988087,1085,1355261909),(988088,1085,1355261912),(988089,1085,1355262062),(988090,1085,1355262129),(988091,1085,1355262154),(988092,1085,1355262155),(988093,1085,1355262159),(988094,1085,1355262197),(988095,1085,1355262226),(988096,1085,1355262236),(988097,1085,1355262257),(988098,1085,1355262315),(988099,1085,1355262315),(988100,1085,1355262331),(988101,1085,1355262344),(988102,1085,1355262483),(988103,1085,1355262392),(988104,1085,1355262422),(988105,1085,1355262424),(988106,1085,1355262470),(988107,1085,1355262483),(988108,1045,1355262505),(988108,1085,1355262492),(988109,1085,1355262624),(988110,1085,1355262713),(988111,1085,1355262732),(988112,1085,1355262747),(988113,1085,1355262760),(988114,1085,1355262797),(988115,1085,1355262801),(988116,1045,1355264001),(988116,1085,1355262836),(988117,1085,1355262845),(988118,1085,1355262885),(988119,1085,1355262934),(988120,1085,1355262990),(988121,1085,1355262994),(988122,1085,1355263018),(988123,1085,1355263024),(988124,1085,1355263073),(988125,1085,1355263081),(988126,1085,1355263107),(988127,1085,1355263108),(988128,1085,1355263116),(988129,1085,1355263123),(988130,1085,1355263126),(988131,1085,1355263156),(988132,1085,1355263195),(988133,1085,1355263212),(988134,1085,1355263240),(988135,1085,1355263258),(988136,1085,1355263279),(988137,1085,1355263291),(988138,1085,1355263356),(988139,1085,1355263452),(988140,1085,1355263418),(988141,1085,1355263428),(988142,1085,1355263511),(988143,1085,1355263519),(988144,1085,1355263533),(988145,1085,1355263533),(988146,1085,1355263572),(988147,1085,1355263594),(988148,1085,1355263612),(988149,1085,1355263656),(988150,1085,1355263658),(988151,1085,1355263676),(988152,1085,1355263702),(988153,1085,1355263749),(988154,1085,1355263746),(988155,1085,1355263767),(988156,1085,1355263780),(988157,1085,1355263790),(988158,1085,1355263821),(988159,1085,1355263974),(988160,1085,1355263983),(988161,1085,1355263932),(988162,1085,1355263953),(988163,1045,1355263970),(988163,1085,1355263956),(988164,1085,1355263961),(988165,1085,1355263985),(988166,1085,1355264050),(988167,1085,1355264100),(988168,1085,1355264164),(988169,1085,1355264182),(988170,1085,1355264221),(988171,1085,1355264280),(988172,1085,1355264314),(988173,1085,1355264342),(988174,1085,1355264424),(988175,1085,1355264448),(988176,1085,1355264508),(988177,1085,1355264516),(988178,1085,1355264557),(988179,1085,1355264581),(988180,1085,1355264581),(988181,1085,1355264639),(988182,1085,1355264602),(988183,1085,1355264631),(988184,1046,1355888648),(988184,1085,1355264644),(988185,1085,1355264655),(988186,1085,1355264675),(988187,1085,1355264702),(988188,1085,1355264766),(988189,1085,1355264784),(988190,1085,1355264816),(988191,1085,1355264817),(988192,1085,1355265020),(988193,1085,1355265021),(988194,1085,1355265050),(988195,1085,1355265070),(988196,1085,1355265071),(988197,1085,1355265076),(988198,1085,1355265103),(988199,1085,1355265117),(988200,1085,1355265143),(988201,1085,1355265146),(988202,1085,1355265146),(988203,1085,1355265189),(988204,1085,1355265266),(988205,1085,1355265318),(988206,1085,1355265322),(988207,1085,1355265399),(988208,1085,1355265410),(988209,1085,1355265479),(988210,1085,1355265495),(988211,1085,1355265499),(988212,1085,1355265520),(988213,1085,1355265525),(988214,1085,1355265577),(988215,1085,1355265594),(988216,1085,1355265598),(988217,1085,1355265611),(988218,1085,1355265662),(988219,1085,1355265760),(988220,1085,1355265784),(988221,1085,1355265823),(988222,1085,1355265824),(988223,1085,1355265842),(988224,1085,1355265998),(988225,1085,1355265886),(988226,1085,1355266033),(988227,1085,1355266037),(988228,1085,1355266462),(988229,1085,1355266212),(988230,1085,1355266247),(988231,1085,1355266281),(988232,1085,1355266283),(988233,1085,1355266322),(988234,1085,1355266462),(988235,1085,1355266365),(988236,1085,1355266373),(988237,1085,1355266397),(988238,1085,1355266401),(988239,1085,1355266483),(988240,1085,1355266504),(988241,1085,1355266621),(988242,1085,1355266652),(988243,1085,1355266677),(988244,1085,1355266681),(988245,1085,1355266777),(988246,1085,1355266783),(988247,1085,1355266798),(988248,1085,1355266871),(988249,1085,1355266879),(988250,1085,1355266893),(988251,1085,1355266909),(988252,1085,1355266946),(988253,1085,1355266954),(988254,1085,1355266955),(988255,1085,1355350517),(988256,1085,1355267114),(988257,1085,1355267120),(988258,1085,1355267172),(988259,1085,1355267188),(988260,1085,1355267254),(988261,1085,1355267258),(988262,1045,1355267283),(988262,1085,1355267269),(988263,1085,1355267273),(988264,1085,1355267291),(988265,1085,1355267299),(988266,1085,1355267311),(988267,1085,1355267348),(988268,1085,1355267360),(988269,1085,1355267383),(988270,1085,1355267404),(988271,1085,1355267414),(988272,1085,1355267505),(988273,1085,1355267491),(988274,1085,1355267566),(988275,1085,1355267601),(988276,1085,1355267605),(988277,1085,1355267707),(988278,1085,1355267710),(988279,1085,1355267715),(988280,1085,1355267732),(988281,1085,1355267763),(988282,1085,1355267784),(988283,1085,1355267792),(988284,1085,1355267818),(988285,1085,1355267852),(988286,1085,1355267912),(988287,1085,1355267936),(988288,1085,1355267957),(988289,1085,1355267972),(988290,1085,1355268006),(988291,1085,1355268020),(988292,1085,1355268050),(988293,1085,1355268071),(988294,1085,1355268110),(988295,1085,1355268130),(988296,1085,1355268142),(988297,1085,1355268205),(988298,1085,1355268209),(988299,1085,1355268217),(988300,1085,1355268259),(988301,1085,1355268279),(988302,1085,1355268611),(988303,1085,1355268389),(988304,1085,1355268400),(988305,1085,1355268405),(988306,1085,1355268406),(988308,1085,1355268476),(988309,1085,1355268513),(988310,1085,1355268563),(988311,1085,1355268592),(988312,1085,1355268602),(988313,1085,1355268628),(988314,1085,1355268628),(988315,1085,1355268672),(988316,1085,1355268727),(988317,1046,1355532713),(988317,1085,1355268734),(988318,1085,1355268744),(988319,1085,1355268763),(988320,1045,1355268806),(988320,1085,1355268801),(988321,1085,1355268961),(988322,1085,1355268829),(988323,1085,1355268904),(988324,1085,1355268955),(988325,1085,1355268991),(988326,1085,1355269009),(988327,1085,1355269041),(988328,1085,1355269171),(988329,1085,1355269180),(988330,1085,1355269181),(988331,1085,1355269254),(988332,1085,1355269264),(988333,1085,1355269269),(988334,1085,1355269278),(988335,1085,1355269308),(988336,1085,1355269340),(988337,1085,1355269349),(988338,1085,1355269404),(988339,1085,1355269435),(988340,1085,1355269445),(988341,1085,1355269534),(988342,1085,1355269505),(988343,1085,1355269513),(988344,1085,1355269553),(988345,1085,1355269578),(988346,1085,1355269578),(988347,1085,1355269587),(988348,1085,1355269702),(988349,1085,1355269610),(988350,1085,1355269621),(988351,1085,1355269643),(988352,1085,1355269654),(988353,1085,1355269658),(988354,1085,1355269696),(988355,1085,1355269701),(988356,1085,1355269755),(988357,1085,1355269756),(988358,1085,1355269827),(988359,1085,1355269828),(988360,1085,1355269865),(988361,1085,1355269921),(988362,1085,1355269928),(988363,1085,1355270016),(988364,1085,1355270035),(988365,1085,1355270042),(988366,1085,1355270106),(988367,1085,1355270117),(988368,1085,1355270126),(988369,1085,1355270207),(988370,1085,1355270322),(988371,1085,1355270375),(988372,1046,1355270778),(988372,1085,1355270441),(988373,1085,1355270471),(988374,1085,1355270486),(988375,1085,1355270535),(988376,1085,1355270621),(988377,1085,1355270630),(988378,1085,1355270630),(988379,1085,1355270673),(988380,1085,1355270707),(988381,1085,1355270715),(988382,1085,1355270765),(988383,1085,1355270757),(988384,1085,1355270872),(988385,1085,1355270890),(988386,1085,1355270910),(988387,1045,1355270942),(988387,1085,1355270924),(988388,1085,1355270943),(988389,1085,1355271013),(988390,1045,1355271104),(988390,1085,1355271101),(988391,1085,1355271069),(988392,1085,1355271176),(988393,1085,1355271248),(988394,1085,1355271285),(988395,1085,1355271286),(988396,1045,1355271327),(988396,1085,1355271312),(988397,1085,1355271361),(988398,1085,1355271364),(988399,1085,1355271372),(988400,1085,1355271403),(988401,1085,1355271492),(988402,1085,1355271520),(988403,1085,1355271556),(988404,1085,1355271563),(988405,1085,1355271601),(988406,1085,1355271588),(988407,1085,1355271761),(988408,1045,1355319562),(988408,1085,1355271786),(988409,1085,1355271893),(988410,1085,1355271923),(988411,1085,1355271987),(988412,1085,1355272008),(988413,1085,1355272052),(988414,1085,1355272067),(988415,1085,1355272093),(988416,1085,1355272135),(988417,1085,1355272154),(988418,1085,1355272170),(988419,1085,1355272171),(988420,1085,1355272221),(988421,1085,1355272247),(988422,1085,1355272247),(988423,1085,1355272257),(988424,1085,1355272280),(988425,1085,1355272345),(988426,1085,1355272357),(988427,1045,1355272378),(988427,1085,1355272357),(988428,1085,1355272360),(988429,1085,1355272377),(988430,1085,1355272380),(988431,1085,1355272380),(988432,1085,1355272431),(988433,1085,1355272454),(988434,1085,1355272478),(988435,1085,1355272516),(988436,1085,1355272542),(988437,1085,1355272549),(988438,1085,1355272654),(988439,1085,1355272655),(988440,1085,1355273317),(988441,1085,1355272680),(988442,1085,1355272728),(988443,1085,1355272766),(988444,1085,1355272788),(988445,1085,1355272822),(988446,1085,1355272852),(988447,1085,1355272943),(988448,1085,1355272976),(988449,1085,1355272980),(988450,1085,1355272994),(988451,1085,1355273005),(988452,1085,1355273043),(988453,1085,1355273044),(988454,1085,1355273113),(988455,1085,1355273133),(988456,1085,1355273135),(988457,1085,1355273176),(988458,1085,1355273224),(988459,1085,1355273244),(988460,1085,1355273279),(988461,1085,1355273506),(988462,1085,1355273564),(988463,1085,1355273607),(988464,1085,1355273628),(988465,1085,1355273648),(988466,1085,1355273676),(988467,1085,1355273676),(988468,1085,1355273734),(988469,1085,1355273749),(988470,1085,1355273765),(988471,1085,1355273766),(988472,1085,1355273856),(988473,1085,1355273866),(988474,1085,1355273922),(988475,1085,1355273924),(988476,1085,1355372653),(988477,1085,1355273935),(988478,1085,1355273943),(988479,1085,1355273997),(988480,1085,1355274002),(988481,1085,1355274015),(988482,1085,1355274055),(988483,1085,1355274197),(988484,1085,1355274327),(988485,1085,1355274248),(988486,1085,1355274320),(988487,1085,1355274328),(988488,1085,1355274359),(988489,1085,1355274384),(988490,1085,1355274438),(988491,1085,1355274463),(988492,1085,1355274511),(988493,1085,1355274518),(988494,1085,1355274532),(988496,1085,1355274562),(988497,1085,1355274590),(988498,1085,1355274602),(988499,1085,1355274663),(988500,1085,1355274800),(988501,1085,1355274854),(988502,1085,1355274859),(988503,1085,1355274913),(988504,1085,1355274961),(988505,1085,1355274987),(988506,1085,1355275029),(988507,1085,1355275074),(988508,1085,1355275105),(988509,1085,1355275105),(988510,1085,1355275110),(988511,1085,1355275115),(988512,1085,1355275158),(988513,1085,1355275156),(988514,1085,1355275191),(988515,1085,1355275246),(988516,1085,1355275216),(988517,1085,1355275218),(988518,1085,1355275317),(988519,1085,1355275351),(988520,1085,1355275329),(988521,1085,1355275460),(988522,1085,1355275467),(988523,1085,1355275473),(988524,1085,1355275536),(988525,1085,1355275499),(988526,1085,1355317481),(988527,1085,1355275538),(988528,1085,1355275583),(988529,1085,1355275632),(988530,1085,1355275696),(988531,1085,1355275719),(988532,1085,1355275747),(988533,1085,1355275841),(988534,1085,1355275862),(988535,1085,1355275900),(988536,1085,1355275981),(988537,1085,1355275994),(988538,1085,1355276117),(988539,1085,1355276039),(988540,1085,1355276097),(988541,1085,1355276122),(988542,1085,1355276148),(988543,1085,1355276199),(988544,1085,1355276205),(988545,1085,1355276288),(988546,1085,1355276319),(988547,1085,1355276320),(988548,1085,1355276330),(988549,1085,1355276427),(988550,1085,1355276508),(988551,1085,1355276499),(988552,1085,1355276500),(988553,1085,1355276541),(988554,1085,1355276641),(988555,1085,1355276693),(988556,1085,1355276786),(988557,1085,1355276803),(988558,1085,1355276828),(988559,1085,1355276846),(988560,1085,1355276913),(988561,1085,1355276954),(988562,1085,1355276935),(988563,1085,1355276955),(988564,1085,1355277046),(988565,1085,1355277007),(988566,1085,1355277046),(988567,1085,1355277100),(988568,1085,1355277105),(988569,1085,1355277151),(988570,1085,1355277164),(988571,1085,1355277255),(988572,1085,1355277296),(988573,1085,1355277400),(988574,1085,1355277423),(988575,1085,1355277447),(988576,1085,1355277494),(988577,1085,1355277540),(988578,1085,1355277567),(988579,1085,1355277642),(988580,1085,1355277897),(988581,1085,1355278050),(988582,1045,1355278097),(988582,1085,1355278074),(988583,1085,1355278166),(988584,1085,1355278215),(988585,1085,1355278217),(988586,1085,1355278241),(988587,1085,1355278300),(988588,1085,1355278361),(988589,1085,1355278367),(988590,1085,1355278473),(988591,1085,1355278506),(988592,1085,1355278515),(988593,1085,1355278561),(988594,1085,1355278567),(988595,1085,1355278584),(988596,1045,1355278837),(988596,1085,1355278587),(988597,1085,1355278638),(988598,1085,1355278639),(988599,1085,1355278692),(988600,1085,1355278732),(988601,1085,1355278768),(988602,1045,1355327903),(988602,1085,1355278754),(988603,1085,1355278761),(988604,1085,1355278762),(988605,1085,1355278844),(988606,1085,1355278877),(988607,1085,1355279135),(988608,1085,1355279206),(988609,1085,1355279222),(988610,1085,1355279290),(988611,1085,1355279345),(988612,1085,1355279365),(988614,1085,1355279518),(988615,1085,1355279593),(988616,1085,1355279610),(988617,1085,1355279637),(988618,1085,1355279723),(988619,1085,1355279725),(988620,1085,1355279808),(988621,1085,1355279809),(988622,1085,1355279815),(988623,1085,1355279884),(988624,1085,1355279932),(988625,1085,1355279945),(988626,1085,1355280015),(988627,1085,1355280021),(988628,1085,1355280025),(988629,1085,1355280059),(988630,1085,1355280077),(988631,1085,1355280124),(988632,1085,1355280135),(988633,1085,1355280251),(988634,1085,1355280375),(988635,1085,1355280382),(988636,1085,1355280509),(988637,1085,1355280665),(988638,1085,1355280679),(988639,1046,1355280823),(988639,1085,1355280689),(988640,1085,1355280704),(988641,1085,1355280756),(988642,1085,1355280758),(988643,1085,1355280825),(988644,1085,1355280840),(988645,1085,1355280869),(988646,1085,1355280891),(988647,1085,1355280900),(988648,1085,1355280992),(988649,1085,1355281113),(988650,1085,1355281167),(988651,1085,1355281205),(988652,1085,1355281516),(988653,1085,1355365737),(988654,1085,1355281617),(988655,1085,1355281654),(988656,1085,1355281685),(988657,1085,1355281804),(988658,1085,1355281908),(988659,1085,1355281935),(988660,1085,1355281959),(988661,1085,1355282014),(988662,1085,1355282042),(988663,1085,1355282045),(988664,1085,1355282078),(988665,1085,1355282165),(988666,1085,1355282165),(988667,1085,1355282240),(988668,1085,1355282281),(988669,1085,1355282284),(988670,1085,1355282308),(988671,1085,1355282339),(988671,1236,1355282703),(988672,1085,1355282351),(988673,1085,1355282367),(988674,1085,1355282373),(988675,1085,1355282425),(988676,1085,1355282428),(988677,1085,1355282429),(988678,1085,1355282435),(988679,1085,1355282477),(988680,1085,1355282547),(988681,1085,1355282572),(988682,1085,1355282643),(988683,1085,1355282667),(988684,1085,1355282728),(988685,1045,1355352406),(988685,1085,1355282734),(988686,1085,1355282815),(988687,1085,1355282895),(988688,1085,1355282929),(988689,1085,1355282935),(988690,1085,1355282945),(988691,1085,1355282997),(988692,1085,1355283035),(988693,1085,1355283077),(988694,1085,1355283089),(988695,1085,1355283107),(988696,1085,1355283181),(988697,1085,1355283194),(988698,1085,1355283199),(988699,1085,1355283206),(988700,1045,1355371886),(988700,1085,1355283264),(988701,1085,1355283314),(988702,1085,1355283458),(988703,1085,1355283523),(988704,1085,1355283520),(988705,1085,1355283870),(988706,1085,1355319047),(988707,1085,1355284344),(988708,1085,1355284107),(988709,1085,1355284210),(988710,1085,1355284223),(988711,1085,1355284258),(988712,1085,1355284305),(988713,1085,1355284348),(988714,1085,1355284441),(988715,1085,1355284501),(988716,1085,1355284540),(988717,1085,1355284627),(988718,1085,1355284752),(988719,1085,1355284924),(988720,1085,1355284934),(988721,1085,1355285108),(988722,1085,1355285118),(988723,1085,1355285132),(988724,1085,1355285204),(988725,1085,1355285251),(988726,1085,1355285260),(988727,1085,1355285260),(988728,1085,1355285304),(988729,1085,1355285317),(988729,1236,1355285427),(988730,1085,1355285324),(988731,1085,1355285365),(988732,1085,1355285400),(988733,1085,1355285502),(988734,1085,1355285547),(988735,1085,1355285558),(988736,1085,1355285578),(988737,1085,1355285736),(988738,1085,1355285812),(988739,1085,1355285920),(988740,1085,1355285914),(988741,1085,1355285950),(988742,1085,1355285991),(988743,1085,1355286171),(988744,1085,1355286189),(988745,1085,1355286273),(988746,1085,1355286378),(988747,1085,1355286380),(988748,1085,1355286480),(988749,1085,1355286498),(988750,1085,1355286569),(988751,1085,1355286655),(988752,1085,1355286685),(988753,1085,1355286715),(988754,1085,1355286713),(988755,1045,1355286740),(988755,1085,1355286725),(988756,1085,1355286776),(988757,1085,1355286799),(988758,1085,1355286927),(988759,1085,1355287022),(988760,1085,1355287119),(988761,1085,1355287206),(988762,1085,1355287257),(988763,1085,1355288571),(988764,1085,1355287533),(988765,1085,1355287534),(988766,1085,1355287576),(988767,1085,1355287578),(988768,1085,1355287683),(988769,1085,1355287774),(988770,1085,1355288003),(988771,1085,1355288142),(988772,1085,1355288240),(988773,1085,1355288272),(988774,1085,1355288432),(988775,1085,1355288504),(988776,1085,1355288530),(988777,1085,1355288544),(988778,1085,1355288575),(988779,1045,1355288609),(988779,1085,1355288644),(988780,1085,1355288603),(988781,1085,1355292315),(988782,1085,1355288638),(988783,1085,1355288639),(988784,1085,1355288734),(988785,1085,1355288735),(988786,1085,1355288855),(988787,1085,1355289286),(988788,1085,1355289353),(988789,1085,1355289409),(988790,1085,1355289516),(988791,1085,1355289585),(988792,1085,1355289719),(988793,1085,1355289772),(988794,1085,1355289892),(988795,1085,1355290100),(988796,1085,1355290105),(988797,1085,1355290115),(988798,1085,1355290525),(988799,1085,1355290323),(988800,1085,1355290363),(988801,1085,1355290531),(988802,1085,1355290621),(988803,1085,1355290667),(988804,1045,1355290692),(988804,1085,1355290691),(988805,1085,1355290717),(988806,1085,1355290833),(988807,1085,1355290936),(988808,1085,1355291027),(988809,1085,1355291198),(988810,1085,1355291230),(988811,1085,1355291266),(988812,1085,1355291601),(988813,1085,1355291655),(988814,1085,1355291655),(988815,1085,1355291716),(988816,1085,1355291771),(988817,1085,1355291855),(988818,1085,1355291883),(988819,1085,1355291891),(988820,1085,1355292097),(988821,1085,1355292240),(988822,1085,1355292241),(988823,1085,1355292294),(988824,1085,1355292337),(988825,1085,1355292694),(988826,1085,1355292973),(988827,1085,1355293242),(988828,1085,1355293596),(988829,1085,1355293860),(988830,1085,1355294172),(988831,1085,1355294512),(988832,1085,1355294419),(988833,1085,1355294503),(988834,1085,1355294546),(988835,1085,1355294608),(988836,1085,1355294847),(988837,1085,1355295191),(988838,1085,1355295397),(988839,1085,1355295402),(988840,1085,1355295466),(988841,1085,1355295534),(988842,1085,1355295624),(988843,1085,1355295751),(988844,1085,1355295862),(988845,1085,1355296248),(988846,1085,1355296562),(988847,1085,1355296653),(988848,1085,1355297474),(988849,1085,1355297703),(988850,1085,1355298004),(988851,1085,1355298672),(988852,1085,1355298911),(988853,1085,1355299461),(988854,1085,1355299673),(988855,1045,1356263548),(988855,1085,1355299693),(988856,1085,1355299775),(988857,1085,1355299977),(988858,1085,1355300141),(988859,1085,1355300672),(988860,1085,1355301527),(988861,1085,1355301967),(988862,1085,1355302111),(988863,1085,1355302241),(988864,1085,1355302509),(988865,1085,1355302546),(988866,1085,1355303113),(988867,1085,1355303438),(988868,1085,1355304634),(988869,1085,1355305158),(988870,1085,1355305191),(988871,1085,1355305501),(988872,1085,1355305857),(988873,1085,1355305924),(988874,1085,1355306849),(988875,1085,1355308283),(988876,1085,1355308964),(988877,1085,1355309046),(988878,1085,1355309099),(988879,1085,1355309409),(988880,1085,1355310252),(988881,1085,1355310333),(988882,1085,1355310547),(988883,1085,1355310890),(988884,1045,1355830220),(988884,1046,1355829854),(988884,1085,1355311258),(988885,1085,1355311380),(988886,1085,1355311437),(988887,1085,1355311858),(988888,1085,1355312011),(988889,1085,1355311992),(988890,1085,1355312239),(988891,1085,1355312479),(988892,1085,1355312739),(988893,1085,1355313542),(988894,1085,1355313761),(988895,1085,1355313823),(988896,1085,1355314556),(988897,1085,1355314817),(988898,1046,1355386177),(988898,1085,1355382200),(988899,1085,1355315006),(988900,1085,1355315047),(988901,1085,1355315287),(988902,1085,1355315315),(988903,1085,1355315319),(988904,1085,1355315473),(988905,1085,1355315596),(988906,1085,1355315699),(988907,1085,1355316107),(988908,1085,1355316302),(988909,1085,1355316375),(988910,1085,1355316397),(988911,1085,1355316610),(988912,1085,1355316533),(988913,1085,1355316645),(988914,1085,1355316817),(988915,1085,1355316916),(988916,1085,1355317136),(988917,1085,1355317206),(988918,1085,1355317216),(988919,1085,1355317306),(988920,1085,1355317341),(988921,1085,1355317354),(988922,1045,1355460746),(988922,1085,1355317482),(988923,1085,1355317596),(988924,1085,1355317787),(988925,1085,1355317946),(988926,1085,1355318231),(988927,1085,1355318511),(988928,1085,1355318812),(988929,1085,1355319015),(988930,1085,1355319121),(988931,1085,1355319186),(988932,1085,1355319300),(988933,1085,1355319379),(988934,1085,1355319388),(988935,1085,1355319603),(988936,1085,1355319919),(988937,1085,1355320013),(988938,1085,1355320151),(988939,1085,1355320194),(988940,1085,1355320250),(988941,1046,1355841533),(988941,1085,1355320339),(988942,1085,1355320651),(988943,1085,1355320661),(988944,1085,1355320759),(988945,1085,1355320986),(988946,1085,1355321086),(988947,1085,1355321393),(988948,1085,1355321448),(988949,1085,1355321526),(988950,1085,1355321644),(988951,1085,1355321755),(988952,1085,1355321950),(988953,1085,1355322058),(988954,1085,1355322150),(988955,1085,1355322180),(988956,1085,1355322189),(988957,1085,1355322292),(988958,1085,1355322325),(988959,1085,1355322433),(988960,1085,1355322482),(988961,1085,1355322626),(988962,1085,1355322727),(988963,1085,1355322851),(988964,1085,1355322978),(988965,1085,1355323498),(988966,1085,1355323584),(988967,1085,1355323597),(988968,1085,1355323618),(988969,1085,1355323756),(988970,1085,1355323787),(988971,1085,1355323791),(988972,1085,1355323862),(988973,1085,1355324243),(988974,1085,1355324282),(988975,1045,1355324457),(988975,1085,1355324442),(988976,1085,1355325096),(988977,1085,1355325111),(988978,1085,1355325291),(988979,1085,1355325452),(988980,1085,1355325534),(988981,1085,1355325549),(988982,1085,1355325741),(988983,1085,1355325863),(988984,1045,1355346309),(988984,1085,1355326428),(988985,1085,1355325964),(988986,1085,1355326069),(988987,1085,1355326085),(988988,1085,1355326163),(988989,1085,1355326182),(988990,1085,1355326230),(988991,1085,1355326295),(988992,1085,1355326337),(988993,1085,1355326933),(988994,1085,1355327109),(988995,1085,1355327381),(988996,1085,1355327471),(988997,1085,1355327609),(988998,1085,1355327924),(988999,1085,1355328035),(989000,1085,1355328333),(989001,1085,1355328457),(989002,1085,1355328599),(989003,1085,1355328776),(989004,1085,1355328908),(989005,1085,1355328964),(989006,1085,1355329064),(989007,1085,1355329225),(989008,1085,1355329287),(989009,1085,1355329313),(989010,1085,1355329485),(989011,1085,1355329626),(989012,1045,1357862138),(989012,1046,1357862116),(989012,1085,1355329778),(989012,1236,1357522293),(989013,1085,1355329998),(989014,1085,1355330192),(989015,1085,1355330311),(989016,1085,1355330488),(989017,1085,1355330543),(989018,1085,1355330715),(989019,1085,1355330964),(989020,1085,1355331044),(989021,1085,1355331145),(989022,1085,1355331576),(989023,1085,1355331657),(989024,1085,1355331788),(989025,1085,1355331969),(989026,1085,1355332006),(989027,1085,1355332034),(989028,1085,1355332292),(989029,1085,1355332390),(989030,1085,1355333015),(989031,1085,1355333100),(989032,1085,1355333115),(989033,1085,1355333191),(989034,1085,1355333400),(989035,1085,1355333818),(989036,1085,1355333550),(989037,1085,1355333915),(989038,1085,1355334491),(989039,1085,1355333958),(989040,1085,1355333988),(989041,1045,1355505941),(989041,1085,1355334036),(989042,1046,1355844898),(989042,1085,1355334140),(989043,1085,1355334304),(989044,1085,1355334386),(989045,1085,1355334612),(989046,1085,1355334902),(989047,1085,1355334917),(989048,1085,1355335064),(989049,1085,1355335228),(989050,1085,1355335238),(989051,1085,1355335569),(989052,1085,1355335814),(989053,1085,1355336153),(989054,1085,1355336380),(989056,1085,1355336561),(989057,1085,1355336571),(989058,1085,1355336723),(989059,1085,1355336857),(989060,1085,1355337068),(989061,1085,1355337212),(989062,1085,1355337275),(989063,1085,1355337470),(989064,1085,1355337557),(989065,1085,1355337615),(989066,1085,1355337649),(989067,1085,1355337915),(989068,1085,1355337968),(989069,1045,1355338087),(989069,1085,1355338071),(989070,1085,1355338107),(989071,1085,1355338146),(989072,1085,1355338172),(989073,1085,1355338332),(989074,1085,1355338489),(989075,1085,1355338901),(989076,1085,1355340138),(989077,1085,1355339783),(989078,1085,1355339859),(989079,1085,1355339938),(989080,1085,1355339949),(989081,1085,1355340096),(989082,1085,1355340696),(989083,1085,1355340813),(989084,1085,1355340882),(989085,1085,1355341135),(989086,1085,1355341486),(989087,1085,1355342088),(989088,1085,1355342247),(989089,1085,1355342326),(989090,1046,1357337488),(989090,1085,1355342353),(989091,1085,1355342399),(989092,1085,1355342419),(989093,1085,1355342839),(989094,1085,1355343007),(989095,1085,1355343218),(989096,1085,1355343748),(989097,1085,1355343851),(989098,1085,1355343867),(989099,1085,1355343963),(989100,1085,1355344061),(989101,1085,1355344248),(989102,1085,1355344621),(989103,1085,1355345557),(989104,1085,1355345744),(989105,1085,1355345796),(989106,1085,1355345883),(989107,1085,1355345996),(989108,1085,1355346058),(989109,1085,1355346104),(989110,1085,1355346164),(989112,1085,1355346502),(989113,1085,1355346523),(989114,1085,1355346604),(989115,1085,1355346631),(989116,1085,1355346877),(989117,1085,1355346946),(989118,1085,1355350021),(989119,1085,1355348045),(989120,1085,1355348234),(989121,1085,1355348361),(989122,1085,1355348549),(989123,1085,1355348573),(989124,1085,1355348631),(989125,1085,1355348947),(989126,1085,1355349071),(989127,1085,1355349117),(989128,1085,1355349125),(989130,1085,1355349277),(989131,1085,1355349313),(989132,1085,1355349420),(989134,1085,1355349501),(989135,1085,1355349641),(989136,1085,1355350088),(989137,1085,1355350084),(989138,1085,1355350129),(989139,1085,1355350283),(989140,1085,1355350866),(989141,1085,1355351252),(989142,1085,1355351472),(989143,1085,1355351572),(989144,1085,1355351742),(989145,1085,1355351837),(989146,1085,1355351895),(989147,1085,1355351945),(989148,1085,1355351987),(989149,1085,1355352152),(989150,1085,1355352182),(989151,1085,1355352619),(989152,1085,1355352691),(989153,1085,1355352771),(989154,1085,1355353157),(989155,1085,1355352969),(989156,1085,1355353111),(989158,1085,1355353228),(989159,1085,1355353416),(989160,1085,1355353665),(989161,1085,1355353674),(989163,1085,1355353900),(989164,1085,1355354394),(989165,1085,1355354397),(989166,1085,1355354888),(989167,1085,1355355087),(989167,1236,1355366878),(989168,1085,1355355332),(989169,1085,1355355278),(989170,1085,1355355308),(989171,1085,1355355714),(989172,1085,1355355810),(989173,1085,1355356089),(989174,1085,1355356226),(989175,1085,1355356227),(989176,1085,1355356523),(989177,1085,1355356866),(989178,1085,1355357310),(989179,1085,1355357335),(989180,1085,1355357947),(989181,1085,1355358253),(989182,1085,1355358281),(989183,1085,1355358529),(989184,1085,1355358584),(989185,1085,1355359128),(989186,1085,1355359437),(989187,1085,1355359745),(989188,1085,1355359848),(989189,1085,1355359906),(989190,1085,1355360022),(989192,1085,1355360075),(989193,1085,1355360175),(989194,1085,1355360446),(989195,1085,1355360662),(989196,1085,1355360811),(989197,1085,1355360986),(989198,1085,1355360992),(989200,1085,1355361304),(989201,1085,1355361374),(989202,1085,1355361396),(989203,1085,1355499339),(989204,1085,1355361442),(989205,1085,1355362259),(989206,1085,1355361764),(989207,1085,1355361768),(989208,1085,1355362083),(989209,1085,1355362280),(989210,1085,1355362359),(989211,1085,1355362425),(989212,1085,1355362499),(989213,1085,1355362807),(989214,1085,1355362832),(989215,1085,1355362852),(989216,1085,1355363456),(989217,1085,1355363987),(989218,1085,1355364171),(989219,1085,1355365055),(989220,1085,1355365261),(989221,1085,1355365279),(989222,1085,1355365431),(989223,1085,1355366185),(989224,1085,1355366460),(989225,1085,1355366815),(989226,1085,1355367033),(989227,1085,1355367066),(989228,1085,1355367192),(989229,1085,1355367267),(989230,1085,1355367363),(989231,1085,1355367428),(989232,1085,1355367733),(989233,1085,1355368178),(989234,1085,1355368589),(989235,1085,1355368877),(989236,1085,1355368975),(989237,1085,1355369086),(989238,1085,1355369247),(989240,1085,1355369485),(989241,1085,1355370403),(989242,1085,1355370051),(989244,1085,1355370461),(989245,1085,1355370451),(989246,1085,1355441957),(989247,1085,1355371024),(989248,1085,1355371444),(989249,1085,1355371784),(989250,1085,1355371901),(989251,1085,1355372542),(989252,1085,1355372896),(989253,1085,1355373539),(989254,1085,1355373439),(989255,1085,1355373671),(989256,1085,1355373721),(989257,1085,1355374187),(989258,1085,1355374354),(989259,1085,1355374696),(989260,1085,1355374719),(989261,1085,1355375444),(989262,1085,1355375832),(989263,1085,1355376138),(989264,1085,1355376702),(989265,1085,1355376789),(989266,1085,1355377692),(989267,1085,1355378906),(989268,1085,1355379660),(989269,1085,1355380444),(989270,1085,1355380707),(989271,1085,1355385975),(989272,1085,1355386403),(989273,1085,1355389012),(989274,1085,1355390827),(989275,1085,1355392252),(989276,1085,1355395491),(989277,1045,1355396884),(989277,1085,1355396881),(989278,1085,1355398075),(989279,1085,1355398251),(989280,1085,1355398936),(989281,1085,1355399915),(989282,1045,1355401709),(989282,1085,1355401706),(989283,1085,1355401864),(989284,1085,1355402522),(989285,1085,1355402699),(989286,1085,1355403051),(989287,1085,1355403267),(989288,1085,1355404075),(989289,1085,1355404305),(989290,1085,1355404323),(989291,1085,1355404800),(989292,1085,1355405966),(989293,1085,1355406437),(989294,1085,1355406343),(989295,1085,1355407013),(989296,1085,1355407655),(989297,1085,1355408080),(989299,1085,1355408735),(989300,1085,1355408767),(989301,1085,1355409052),(989302,1085,1355409899),(989303,1085,1355410020),(989304,1085,1355410150),(989305,1085,1355410156),(989306,1085,1355410192),(989307,1085,1355411160),(989308,1085,1355411193),(989309,1085,1355411573),(989310,1085,1355411649),(989311,1085,1355411806),(989312,1085,1355411952),(989313,1085,1355412037),(989314,1085,1355412251),(989315,1085,1355413732),(989316,1085,1355413961),(989317,1085,1355414566),(989318,1085,1355415169),(989319,1085,1355415224),(989320,1085,1355415337),(989321,1085,1355415356),(989322,1085,1355415488),(989323,1085,1355415842),(989324,1085,1355415992),(989325,1085,1355416069),(989326,1085,1355417017),(989327,1085,1355417533),(989328,1085,1355417746),(989329,1085,1355419225),(989331,1085,1355420539),(989332,1085,1355421193),(989333,1085,1355421287),(989334,1085,1355421956),(989335,1085,1355422085),(989336,1085,1355422436),(989337,1085,1355422485),(989338,1085,1355422766),(989339,1085,1355422834),(989340,1085,1355423194),(989341,1085,1355423230),(989342,1085,1355423924),(989343,1085,1355424275),(989344,1085,1355424616),(989345,1085,1355424835),(989346,1085,1355425058),(989346,1236,1355426173),(989347,1085,1355425083),(989348,1085,1355425214),(989349,1085,1355426424),(989350,1085,1355426742),(989351,1085,1355427008),(989352,1085,1355427038),(989353,1085,1355428345),(989354,1085,1355428738),(989355,1085,1355429585),(989356,1085,1355430115),(989357,1085,1355430121),(989358,1085,1355430168),(989359,1085,1355430284),(989360,1085,1355430384),(989361,1085,1355431744),(989362,1085,1355432765),(989363,1085,1355432911),(989364,1085,1355432912),(989365,1085,1355433056),(989366,1085,1355433191),(989367,1085,1355433478),(989368,1085,1355434505),(989369,1085,1355435163),(989370,1085,1355436515),(989371,1085,1355436557),(989373,1085,1355436863),(989374,1085,1355437348),(989375,1085,1355437721),(989376,1085,1355437910),(989377,1085,1355438733),(989378,1085,1355438964),(989379,1085,1355438969),(989380,1046,1355872675),(989380,1085,1355439153),(989381,1085,1355439372),(989382,1085,1355440527),(989383,1085,1355442707),(989384,1085,1355443087),(989385,1085,1355443883),(989386,1085,1355445621),(989387,1085,1355446434),(989388,1085,1355446617),(989390,1085,1355447024),(989391,1085,1355448241),(989392,1085,1355448738),(989393,1085,1355449464),(989394,1085,1355449876),(989395,1085,1355449905),(989396,1085,1355450275),(989398,1085,1355451039),(989399,1085,1355451249),(989400,1085,1355452293),(989401,1085,1355452430),(989402,1085,1355452825),(989403,1085,1355453196),(989404,1085,1355453265),(989405,1046,1355926908),(989405,1085,1355453362),(989406,1085,1355453698),(989407,1085,1355453890),(989408,1085,1355454026),(989409,1085,1355454617),(989410,1085,1355454832),(989411,1085,1355456428),(989412,1085,1355456667),(989413,1085,1355456880),(989414,1085,1355457386),(989415,1085,1355457445),(989416,1045,1356985788),(989416,1085,1355457940),(989416,1227,1356985787),(989418,1085,1355459010),(989419,1085,1355459106),(989420,1085,1355460901),(989421,1085,1355461684),(989422,1085,1355462984),(989423,1085,1355464674),(989424,1085,1355466948),(989426,1085,1355467227),(989427,1085,1355468889),(989428,1085,1355471513),(989429,1085,1355471776),(989430,1085,1355476838),(989431,1085,1355477423),(989432,1085,1355486184),(989433,1085,1355486877),(989434,1085,1355488577),(989434,1236,1356729607),(989435,1085,1355490459),(989436,1085,1355490618),(989437,1085,1355491185),(989438,1085,1355492998),(989439,1085,1355494483),(989441,1085,1355495504),(989442,1085,1355495650),(989443,1085,1355496602),(989444,1085,1355498089),(989445,1085,1355499491),(989446,1085,1355500374),(989447,1085,1355500592),(989448,1085,1355501913),(989449,1085,1355502082),(989450,1085,1355502952),(989451,1085,1355504428),(989452,1085,1355507103),(989453,1085,1355507495),(989454,1085,1355507668),(989455,1045,1355518177),(989460,1045,1355538674),(989462,1045,1355547949),(989463,1045,1355554753),(989465,1045,1355584499),(989471,1045,1355682702),(989479,1045,1355766003),(989479,1046,1355840513),(989480,1045,1355770113),(989483,1045,1355805673),(989484,1045,1355807103),(989486,1045,1355814057),(989488,1045,1355875499),(989489,1046,1355832052),(989490,1045,1355834248),(989492,1046,1355836581),(989496,1046,1355839091),(989499,1045,1355842548),(989500,1046,1355842798),(989501,1045,1355844183),(989502,1045,1357359376),(989503,1046,1355847487),(989505,1046,1355847981),(989508,11937,1355852770),(989508,11945,1355851641),(989512,1045,1355853395),(989513,1046,1355854314),(989514,1045,1355855459),(989516,1045,1355856424),(989518,1045,1355861946),(989519,1045,1355862636),(989520,1045,1355863931),(989520,1046,1355864063),(989521,1045,1355865730),(989522,1045,1355866565),(989523,1045,1355866771),(989524,1045,1355866861),(989525,1046,1355867193),(989527,1045,1355867588),(989529,1045,1355872461),(989530,1045,1355872547),(989531,1045,1355872651),(989532,1045,1355873738),(989533,1045,1355874120),(989534,1045,1355875325),(989535,1045,1355877854),(989537,1045,1355881089),(989537,1046,1355881191),(989538,1045,1355881102),(989539,1045,1355881306),(989540,1045,1355882872),(989541,1045,1355883083),(989542,1045,1355884720),(989543,1046,1355894007),(989544,1045,1355902720),(989545,1045,1355907825),(989552,1045,1355952345),(989554,1045,1355992406),(989560,1045,1356047443),(989566,1045,1356179148),(989569,1046,1356238551),(989574,1045,1356378901),(989575,1045,1356406249),(989580,1045,1356561614),(989582,307,1356592235),(989584,1045,1357440994),(989585,1045,1356669404),(989587,1046,1356681375),(989593,1045,1356745637),(989597,1045,1356965411),(989600,1046,1357265015),(989600,11945,1357214817),(989600,11949,1357214675),(989600,11950,1357214738),(989610,1046,1357265756),(989611,1046,1357097556),(989612,1046,1357248553),(989613,1046,1357097556),(989615,1236,1357105869),(989616,1045,1357133547),(989624,1046,1357573052),(989628,1045,1357173859),(989629,1045,1357195720),(989632,1045,1357223023),(989632,1046,1357223136),(989633,1045,1357224902),(989635,1046,1357332080),(989640,1046,1357244937),(989643,1045,1357245373),(989645,1045,1357247294),(989646,1045,1357932479),(989648,1045,1357404613),(989649,1045,1357249652),(989651,1045,1357331994),(989651,1046,1357341000),(989654,1045,1357353903),(989659,1046,1357451597),(989660,1236,1357280501),(989663,1045,1357302541),(989664,1045,1357317179),(989669,1046,1357328677),(989675,1236,1357328165),(989678,1045,1357336200),(989678,1046,1357336192),(989679,1046,1357336420),(989680,1046,1357336541),(989686,1046,1357355172),(989688,1045,1357375659),(989692,1045,1357402003),(989693,1045,1357404787),(989694,1045,1357408816),(989694,1236,1357408762),(989696,1046,1357411238),(989699,1045,1357417545),(989703,1045,1357473040),(989704,1045,1357478399),(989705,1045,1357483939),(989705,1236,1357483855),(989706,1045,1357493780),(989708,1045,1357532439),(989709,1045,1357566713),(989715,1045,1357604614),(989719,1045,1357669397),(989721,1045,1357689047),(989723,1045,1357705404),(989724,1045,1357747845),(989730,1045,1357761276),(989732,1046,1357762349),(989734,1236,1357770250),(989738,1045,1357774748),(989741,1045,1357787836),(989747,1045,1357831786),(989765,1045,1357954473),(989768,1046,1357987805),(989776,1045,1358034502),(989776,1227,1358034500),(989777,1045,1358048378),(989780,1236,1358115798); +/*!40000 ALTER TABLE `history` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +USE percona; +INSERT INTO `checksums` VALUES ('bug918056','history',1,0.002691,'PRIMARY','21,21,1045','19468,19468,1045','411dd838',1000,'411dd838',1000,'2013-01-23 15:00:17'),('bug918056','history',2,0.019143,'PRIMARY','19514,19514,1046','989780,989780,1236','39bdd8db',11650,'39bdd8db',11650,'2013-01-23 15:00:17'),('bug918056','history',3,0.000658,'PRIMARY',NULL,'21,21,1045','0',49,'0',0,'2013-01-23 15:00:17'),('bug918056','history',4,0.000586,'PRIMARY','989780,989780,1236',NULL,'0',0,'0',0,'2013-01-23 15:00:17'); diff --git a/t/pt-table-sync/samples/upper-oob-master.sql b/t/pt-table-sync/samples/upper-oob-master.sql new file mode 100644 index 00000000..10feb36e --- /dev/null +++ b/t/pt-table-sync/samples/upper-oob-master.sql @@ -0,0 +1,148 @@ +DROP DATABASE IF EXISTS upper_oob; +CREATE DATABASE upper_oob; +USE upper_oob; + +CREATE TABLE t ( + id int not null auto_increment primary key, + c varchar(64) +) engine=innodb; + +insert into t values +(1, 'Afghanistan'), +(2, 'Algeria'), +(3, 'American Samoa'), +(4, 'Angola'), +(5, 'Anguilla'), +(6, 'Argentina'), +(7, 'Armenia'), +(8, 'Australia'), +(9, 'Austria'), +(10, 'Azerbaijan'), +(11, 'Bahrain'), +(12, 'Bangladesh'), +(13, 'Belarus'), +(14, 'Bolivia'), +(15, 'Brazil'), +(16, 'Brunei'), +(17, 'Bulgaria'), +(18, 'Cambodia'), +(19, 'Cameroon'), +(20, 'Canada'), +(21, 'Chad'), +(22, 'Chile'), +(23, 'China'), +(24, 'Colombia'), +(25, 'Congo, The Democratic Republic of the'), +(26, 'Czech Republic'), +(27, 'Dominican Republic'), +(28, 'Ecuador'), +(29, 'Egypt'), +(30, 'Estonia'), +(31, 'Ethiopia'), +(32, 'Faroe Islands'), +(33, 'Finland'), +(34, 'France'), +(35, 'French Guiana'), +(36, 'French Polynesia'), +(37, 'Gambia'), +(38, 'Germany'), +(39, 'Greece'), +(40, 'Greenland'), +(41, 'Holy See (Vatican City State)'), +(42, 'Hong Kong'), +(43, 'Hungary'), +(44, 'India'), +(45, 'Indonesia'), +(46, 'Iran'), +(47, 'Iraq'), +(48, 'Israel'), +(49, 'Italy'), +(50, 'Japan'), +(51, 'Kazakstan'), +(52, 'Kenya'), +(53, 'Kuwait'), +(54, 'Latvia'), +(55, 'Liechtenstein'), +(56, 'Lithuania'), +(57, 'Madagascar'), +(58, 'Malawi'), +(59, 'Malaysia'), +(60, 'Mexico'), +(61, 'Moldova'), +(62, 'Morocco'), +(63, 'Mozambique'), +(64, 'Myanmar'), +(65, 'Nauru'), +(66, 'Nepal'), +(67, 'Netherlands'), +(68, 'New Zealand'), +(69, 'Nigeria'), +(70, 'North Korea'), +(71, 'Oman'), +(72, 'Pakistan'), +(73, 'Paraguay'), +(74, 'Peru'), +(75, 'Philippines'), +(76, 'Poland'), +(77, 'Puerto Rico'), +(78, 'Romania'), +(79, 'Runion'), +(80, 'Russian Federation'), +(81, 'Saint Vincent and the Grenadines'), +(82, 'Saudi Arabia'), +(83, 'Senegal'), +(84, 'Slovakia'), +(85, 'South Africa'), +(86, 'South Korea'), +(87, 'Spain'), +(88, 'Sri Lanka'), +(89, 'Sudan'), +(90, 'Sweden'), +(91, 'Switzerland'), +(92, 'Taiwan'), +(93, 'Tanzania'), +(94, 'Thailand'), +(95, 'Tonga'), +(96, 'Tunisia'), +(97, 'Turkey'), +(98, 'Turkmenistan'), +(99, 'Tuvalu'), +(100, 'Ukraine'), +(101, 'United Arab Emirates'), +(102, 'United Kingdom'), +(103, 'United States'), +(104, 'Venezuela'), +(105, 'Vietnam'), +(106, 'Virgin Islands, U.S.'), +(107, 'Yemen'), +(108, 'Yugoslavia'), +(109, 'Zambia'); + +CREATE DATABASE IF NOT EXISTS percona; +USE percona; +DROP TABLE IF EXISTS checksums; +CREATE TABLE `checksums` ( + `db` char(64) NOT NULL, + `tbl` char(64) NOT NULL, + `chunk` int(11) NOT NULL, + `chunk_time` float DEFAULT NULL, + `chunk_index` varchar(200) DEFAULT NULL, + `lower_boundary` text, + `upper_boundary` text, + `this_crc` char(40) NOT NULL, + `this_cnt` int(11) NOT NULL, + `master_crc` char(40) DEFAULT NULL, + `master_cnt` int(11) DEFAULT NULL, + `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`db`,`tbl`,`chunk`), + KEY `ts_db_tbl` (`ts`,`db`,`tbl`) +) ENGINE=InnoDB; + +SET SQL_LOG_BIN=0; +DELETE FROM upper_oob.t where id > 99; +INSERT INTO percona.checksums VALUES + ('upper_oob','t',1,0.001144,'PRIMARY','1','50','398f3270',50,'398f3270',50,'2013-01-23 17:36:56'), + ('upper_oob','t',2,0.000878,'PRIMARY','51','99','bd9a892d',49,'bd9a892d',49,'2013-01-23 17:36:56'), + ('upper_oob','t',3,0.000763,'PRIMARY',NULL,'1','0',0,'0',0,'2013-01-23 17:36:56'), + ('upper_oob','t',4,0.000877,'PRIMARY','99',NULL,'0',0,'0',0,'2013-01-23 17:36:56'); +SET SQL_LOG_BIN=1; diff --git a/t/pt-table-sync/samples/upper-oob-print.txt b/t/pt-table-sync/samples/upper-oob-print.txt new file mode 100644 index 00000000..e5eca9dd --- /dev/null +++ b/t/pt-table-sync/samples/upper-oob-print.txt @@ -0,0 +1,10 @@ +DELETE FROM `upper_oob`.`t` WHERE `id`='100' LIMIT 1; +DELETE FROM `upper_oob`.`t` WHERE `id`='101' LIMIT 1; +DELETE FROM `upper_oob`.`t` WHERE `id`='102' LIMIT 1; +DELETE FROM `upper_oob`.`t` WHERE `id`='103' LIMIT 1; +DELETE FROM `upper_oob`.`t` WHERE `id`='104' LIMIT 1; +DELETE FROM `upper_oob`.`t` WHERE `id`='105' LIMIT 1; +DELETE FROM `upper_oob`.`t` WHERE `id`='106' LIMIT 1; +DELETE FROM `upper_oob`.`t` WHERE `id`='107' LIMIT 1; +DELETE FROM `upper_oob`.`t` WHERE `id`='108' LIMIT 1; +DELETE FROM `upper_oob`.`t` WHERE `id`='109' LIMIT 1; diff --git a/t/pt-table-sync/samples/upper-oob-slave.sql b/t/pt-table-sync/samples/upper-oob-slave.sql new file mode 100644 index 00000000..1cfdafab --- /dev/null +++ b/t/pt-table-sync/samples/upper-oob-slave.sql @@ -0,0 +1,7 @@ +USE percona; +TRUNCATE TABLE checksums; +INSERT INTO `checksums` VALUES +('upper_oob','t',1,0.001144,'PRIMARY','1','50','398f3270',50,'398f3270',50,'2013-01-23 17:36:56'), +('upper_oob','t',2,0.000878,'PRIMARY','51','99','bd9a892d',49,'bd9a892d',49,'2013-01-23 17:36:56'), +('upper_oob','t',3,0.000763,'PRIMARY',NULL,'1','0',0,'0',0,'2013-01-23 17:36:56'), +('upper_oob','t',4,0.000877,'PRIMARY','99',NULL,'0',10,'0',0,'2013-01-23 17:36:56'); diff --git a/util/build-packages b/util/build-packages index b219d668..33c35360 100755 --- a/util/build-packages +++ b/util/build-packages @@ -181,7 +181,7 @@ update_copyright_year() { echo -n "Updating copyright year in tools... " cd $BRANCH/bin for tool_file in *; do - local copyright="$(grep "[0-9] Percona Inc." $tool_file)" + local copyright="$(grep "[0-9] Percona Ireland Ltd" $tool_file)" local new_copyright="$(../util/new-copyright-year "$YEAR" "$copyright")" if [ $? -ne 0 ]; then die "Error parsing copyright year in $tool_file" @@ -196,7 +196,7 @@ update_copyright_year() { echo -n "Updating copyright year in percona-toolkit.pod... " local pod=$DOCS_DIR/percona-toolkit.pod - local copyright="$(grep "[0-9] Percona Inc." $pod)" + local copyright="$(grep "[0-9] Percona Ireland Ltd" $pod)" local new_copyright="$(../util/new-copyright-year "$YEAR" "$copyright")" if [ $? -ne 0 ]; then die "Error parsing copyright year in percona-toolkit.pod" diff --git a/util/test-bash-functions b/util/test-bash-functions index 2616c7c8..53639158 100755 --- a/util/test-bash-functions +++ b/util/test-bash-functions @@ -100,6 +100,7 @@ run_test() { result() { local result=$1 local test_name=${2:-""} + testno=$((testno + 1)) if [ $result -eq 0 ]; then echo "ok $testno - $TEST_FILE $test_name" else @@ -110,7 +111,6 @@ result() { cat $TEST_PT_TMPDIR/failed_result | sed -e 's/^/# /' -e '30q' >&2 fi fi - testno=$((testno + 1)) return $result } @@ -121,19 +121,21 @@ plan() { fi } +done_testing() { + echo "1..$testno" +} + # # The following subs are for the test files to call. # pass() { local reason="${1:-""}" - result 0 "$reason" } fail() { local reason="${1:-""}" - result 1 "$reason" } @@ -177,6 +179,42 @@ is() { result $? "$test_name" } +file_is_empty() { + local file=$1 + local test_name=${2:-""} + test_command="-s $file" + if [ ! -f "$file" ]; then + echo "$file does not exist" > $TEST_PT_TMPDIR/failed_result + result 1 "$test_name" + fi + if [ -s "$file" ]; then + echo "$file is not empty:" > $TEST_PT_TMPDIR/failed_result + cat "$file" >> $TEST_PT_TMPDIR/failed_result + result 1 "$test_name" + else + result 0 "$test_name" + fi +} + +file_contains() { + local file="$1" + local pat="$2" + local test_name=${3:-""} + test_command="grep -q '$pat' '$file'" + if [ ! -f "$file" ]; then + echo "$file does not exist" > $TEST_PT_TMPDIR/failed_result + result 1 "$test_name" + fi + grep -q "$pat" $file + if [ $? -ne 0 ]; then + echo "$file does not contain '$pat':" > $TEST_PT_TMPDIR/failed_result + cat "$file" >> $TEST_PT_TMPDIR/failed_result + result 1 "$test_name" + else + result 0 "$test_name" + fi +} + cmd_ok() { local test_command=$1 local test_name=${2:-""} @@ -226,7 +264,7 @@ diag() { # Script starts here # ############################################################################ -testno=1 +testno=0 failed_tests=0 if [ $# -eq 0 ]; then diff --git a/util/update-modules b/util/update-modules index f17fa695..954729cb 100755 --- a/util/update-modules +++ b/util/update-modules @@ -190,13 +190,13 @@ if [ $pkgs_updated -gt 0 ]; then fi if [ $EXIT_STATUS -eq 0 ]; then cp $tmp_tool_file $tool_file + EXIT_STATUS=$((EXIT_STATUS | $?)) if [ $? -ne 0 ]; then warn "Failed to copy $tmp_tool_file to $tool_file" - else - rm $tmp_tool_file > /dev/null - EXIT_STATUS=$((EXIT_STATUS | $?)) fi fi fi +[ -f "$tmp_tool_file" ] && rm $tmp_tool_file + exit $EXIT_STATUS