diff --git a/Changelog b/Changelog index a1653c80..c33079ee 100644 --- a/Changelog +++ b/Changelog @@ -1,5 +1,10 @@ Changelog for Percona Toolkit +v3.0.7 + + * Feature PT-644 : Added --mysql-only option to pt-stalk for RDS + * Fixed bug PT-1256: pt-table-sync does not use the character set for the table it is synchronizing + v3.0.6 released 2017-12-20 * Fixed bug PT-234: Genaral log parser cannot handle timestamps with tz diff --git a/bin/pt-archiver b/bin/pt-archiver index d08e95ed..b297def3 100755 --- a/bin/pt-archiver +++ b/bin/pt-archiver @@ -5373,15 +5373,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -5598,6 +5599,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -5634,7 +5675,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-config-diff b/bin/pt-config-diff index 7a340806..35b0134f 100755 --- a/bin/pt-config-diff +++ b/bin/pt-config-diff @@ -4711,15 +4711,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -4936,6 +4937,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -4972,7 +5013,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-deadlock-logger b/bin/pt-deadlock-logger index d2b09b78..4ed24bb3 100755 --- a/bin/pt-deadlock-logger +++ b/bin/pt-deadlock-logger @@ -3775,15 +3775,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -4000,6 +4001,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -4036,7 +4077,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-diskstats b/bin/pt-diskstats index 9773fd84..a1bb8252 100755 --- a/bin/pt-diskstats +++ b/bin/pt-diskstats @@ -4328,15 +4328,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -4553,6 +4554,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -4589,7 +4630,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-duplicate-key-checker b/bin/pt-duplicate-key-checker index d6586855..9cca3223 100755 --- a/bin/pt-duplicate-key-checker +++ b/bin/pt-duplicate-key-checker @@ -4379,15 +4379,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -4604,6 +4605,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -4640,7 +4681,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-find b/bin/pt-find index c1e4a940..e63870c9 100755 --- a/bin/pt-find +++ b/bin/pt-find @@ -3093,15 +3093,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -3318,6 +3319,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -3354,7 +3395,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-fk-error-logger b/bin/pt-fk-error-logger index 8ce7b713..e99aae70 100755 --- a/bin/pt-fk-error-logger +++ b/bin/pt-fk-error-logger @@ -3280,15 +3280,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -3505,6 +3506,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -3541,7 +3582,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-heartbeat b/bin/pt-heartbeat index b3be48c7..f0566be2 100755 --- a/bin/pt-heartbeat +++ b/bin/pt-heartbeat @@ -4980,15 +4980,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -5205,6 +5206,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -5241,7 +5282,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-index-usage b/bin/pt-index-usage index 75239c1f..d34f34a4 100755 --- a/bin/pt-index-usage +++ b/bin/pt-index-usage @@ -5777,15 +5777,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -6002,6 +6003,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -6038,7 +6079,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-kill b/bin/pt-kill index 01154183..5e1fd437 100755 --- a/bin/pt-kill +++ b/bin/pt-kill @@ -6185,15 +6185,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -6410,6 +6411,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -6446,7 +6487,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-online-schema-change b/bin/pt-online-schema-change index 0804bb84..89505e66 100755 --- a/bin/pt-online-schema-change +++ b/bin/pt-online-schema-change @@ -7414,15 +7414,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -7639,6 +7640,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -7675,7 +7716,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-query-digest b/bin/pt-query-digest index ba90a55f..4923c3cb 100755 --- a/bin/pt-query-digest +++ b/bin/pt-query-digest @@ -12446,15 +12446,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -12671,6 +12672,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -12707,7 +12748,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-slave-delay b/bin/pt-slave-delay index e79bd633..0ff73c59 100755 --- a/bin/pt-slave-delay +++ b/bin/pt-slave-delay @@ -3597,15 +3597,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -3822,6 +3823,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -3858,7 +3899,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-slave-restart b/bin/pt-slave-restart index f202ff2a..59cd6315 100755 --- a/bin/pt-slave-restart +++ b/bin/pt-slave-restart @@ -4306,15 +4306,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -4531,6 +4532,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -4567,7 +4608,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-stalk b/bin/pt-stalk index 82a64df6..9bdf2ef0 100755 --- a/bin/pt-stalk +++ b/bin/pt-stalk @@ -128,6 +128,7 @@ OPT_ERRS=0 # How many command line option errors OPT_VERSION="" # If --version was specified OPT_HELP="" # If --help was specified OPT_ASK_PASS="" # If --ask-pass was specified +OPT_MYSQL_ONLY="" # If --mysql-only was specified PO_DIR="" # Directory with program option spec files usage() { @@ -795,7 +796,10 @@ collect() { local d="$1" # directory to save results in local p="$2" # prefix for each result file - local mysqld_pid=$(_pidof mysqld | awk '{print $1; exit;}') + local mysqld_pid="" + if [ ! "$OPT_MYSQL_ONLY" ]; then + mysqld_pid=$(_pidof mysqld | awk '{print $1; exit;}') + fi if [ "$CMD_PMAP" -a "$mysqld_pid" ]; then if $CMD_PMAP --help 2>&1 | grep -- -x >/dev/null 2>&1 ; then @@ -824,7 +828,7 @@ collect() { fi local tail_error_log_pid="" - if [ "$mysql_error_log" ]; then + if [ "$mysql_error_log" -a ! "$OPT_MYSQL_ONLY" ]; then log "The MySQL error log seems to be $mysql_error_log" tail -f "$mysql_error_log" >"$d/$p-log_error" & tail_error_log_pid=$! @@ -865,37 +869,39 @@ collect() { local strace_pid=$! fi - ps -eaF >> "$d/$p-ps" & - top -bn${OPT_RUN_TIME} >> "$d/$p-top" & + if [ ! "$OPT_MYSQL_ONLY" ]; then + ps -eaF >> "$d/$p-ps" & + top -bn${OPT_RUN_TIME} >> "$d/$p-top" & - [ "$mysqld_pid" ] && _lsof $mysqld_pid >> "$d/$p-lsof" & + [ "$mysqld_pid" ] && _lsof $mysqld_pid >> "$d/$p-lsof" & - if [ "$CMD_SYSCTL" ]; then - $CMD_SYSCTL -a >> "$d/$p-sysctl" & - fi + if [ "$CMD_SYSCTL" ]; then + $CMD_SYSCTL -a >> "$d/$p-sysctl" & + fi - if [ "$CMD_DMESG" ]; then - local UPTIME=`cat /proc/uptime | awk '{ print $1 }'` - local START_TIME=$(echo "$UPTIME 60" | awk '{print ($1 - $2)}') - $CMD_DMESG | perl -ne 'm/\[\s*(\d+)\./; if ($1 > '${START_TIME}') { print }' >> "$d/$p-dmesg" & - fi + if [ "$CMD_DMESG" ]; then + local UPTIME=`cat /proc/uptime | awk '{ print $1 }'` + local START_TIME=$(echo "$UPTIME 60" | awk '{print ($1 - $2)}') + $CMD_DMESG | perl -ne 'm/\[\s*(\d+)\./; if ($1 > '${START_TIME}') { print }' >> "$d/$p-dmesg" & + fi - local cnt=$(($OPT_RUN_TIME / $OPT_SLEEP_COLLECT)) - if [ "$CMD_VMSTAT" ]; then - $CMD_VMSTAT $OPT_SLEEP_COLLECT $cnt >> "$d/$p-vmstat" & - $CMD_VMSTAT $OPT_RUN_TIME 2 >> "$d/$p-vmstat-overall" & - fi - if [ "$CMD_IOSTAT" ]; then - $CMD_IOSTAT -dx $OPT_SLEEP_COLLECT $cnt >> "$d/$p-iostat" & - $CMD_IOSTAT -dx $OPT_RUN_TIME 2 >> "$d/$p-iostat-overall" & - fi - if [ "$CMD_MPSTAT" ]; then - $CMD_MPSTAT -P ALL $OPT_SLEEP_COLLECT $cnt >> "$d/$p-mpstat" & - $CMD_MPSTAT -P ALL $OPT_RUN_TIME 1 >> "$d/$p-mpstat-overall" & - fi + local cnt=$(($OPT_RUN_TIME / $OPT_SLEEP_COLLECT)) + if [ "$CMD_VMSTAT" ]; then + $CMD_VMSTAT $OPT_SLEEP_COLLECT $cnt >> "$d/$p-vmstat" & + $CMD_VMSTAT $OPT_RUN_TIME 2 >> "$d/$p-vmstat-overall" & + fi + if [ "$CMD_IOSTAT" ]; then + $CMD_IOSTAT -dx $OPT_SLEEP_COLLECT $cnt >> "$d/$p-iostat" & + $CMD_IOSTAT -dx $OPT_RUN_TIME 2 >> "$d/$p-iostat-overall" & + fi + if [ "$CMD_MPSTAT" ]; then + $CMD_MPSTAT -P ALL $OPT_SLEEP_COLLECT $cnt >> "$d/$p-mpstat" & + $CMD_MPSTAT -P ALL $OPT_RUN_TIME 1 >> "$d/$p-mpstat-overall" & + fi - $CMD_MYSQLADMIN $EXT_ARGV ext -i$OPT_SLEEP_COLLECT -c$cnt >>"$d/$p-mysqladmin" & - local mysqladmin_pid=$! + $CMD_MYSQLADMIN $EXT_ARGV ext -i$OPT_SLEEP_COLLECT -c$cnt >>"$d/$p-mysqladmin" & + local mysqladmin_pid=$! + fi local have_lock_waits_table="" $CMD_MYSQL $EXT_ARGV -e "SHOW TABLES FROM INFORMATION_SCHEMA" \ @@ -915,40 +921,41 @@ collect() { fi while [ $((curr_time - start_time)) -lt $OPT_RUN_TIME ]; do + if [ ! "$OPT_MYSQL_ONLY" ]; then + disk_space $d > $d/$p-disk-space + check_disk_space \ + $d/$p-disk-space \ + "$OPT_DISK_BYTES_FREE" \ + "$OPT_DISK_PCT_FREE" \ + || break - disk_space $d > $d/$p-disk-space - check_disk_space \ - $d/$p-disk-space \ - "$OPT_DISK_BYTES_FREE" \ - "$OPT_DISK_PCT_FREE" \ - || break + sleep $(date +'%s.%N' | awk "{print $OPT_SLEEP_COLLECT - (\$1 % $OPT_SLEEP_COLLECT)}") + local ts="$(date +"TS %s.%N %F %T")" - sleep $(date +'%s.%N' | awk "{print $OPT_SLEEP_COLLECT - (\$1 % $OPT_SLEEP_COLLECT)}") - local ts="$(date +"TS %s.%N %F %T")" - - if [ -d "/proc" ]; then - if [ -f "/proc/diskstats" ]; then - (echo $ts; cat /proc/diskstats) >> "$d/$p-diskstats" & - fi - if [ -f "/proc/stat" ]; then - (echo $ts; cat /proc/stat) >> "$d/$p-procstat" & - fi - if [ -f "/proc/vmstat" ]; then - (echo $ts; cat /proc/vmstat) >> "$d/$p-procvmstat" & - fi - if [ -f "/proc/meminfo" ]; then - (echo $ts; cat /proc/meminfo) >> "$d/$p-meminfo" & - fi - if [ -f "/proc/slabinfo" ]; then - (echo $ts; cat /proc/slabinfo) >> "$d/$p-slabinfo" & - fi - if [ -f "/proc/interrupts" ]; then - (echo $ts; cat /proc/interrupts) >> "$d/$p-interrupts" & + if [ -d "/proc" ]; then + if [ -f "/proc/diskstats" ]; then + (echo $ts; cat /proc/diskstats) >> "$d/$p-diskstats" & + fi + if [ -f "/proc/stat" ]; then + (echo $ts; cat /proc/stat) >> "$d/$p-procstat" & + fi + if [ -f "/proc/vmstat" ]; then + (echo $ts; cat /proc/vmstat) >> "$d/$p-procvmstat" & + fi + if [ -f "/proc/meminfo" ]; then + (echo $ts; cat /proc/meminfo) >> "$d/$p-meminfo" & + fi + if [ -f "/proc/slabinfo" ]; then + (echo $ts; cat /proc/slabinfo) >> "$d/$p-slabinfo" & + fi + if [ -f "/proc/interrupts" ]; then + (echo $ts; cat /proc/interrupts) >> "$d/$p-interrupts" & + fi fi + (echo $ts; df -k) >> "$d/$p-df" & + (echo $ts; netstat -antp) >> "$d/$p-netstat" & + (echo $ts; netstat -s) >> "$d/$p-netstat_s" & fi - (echo $ts; df -k) >> "$d/$p-df" & - (echo $ts; netstat -antp) >> "$d/$p-netstat" & - (echo $ts; netstat -s) >> "$d/$p-netstat_s" & (echo $ts; $CMD_MYSQL $EXT_ARGV -e "SHOW FULL PROCESSLIST\G") \ >> "$d/$p-processlist" & if [ "$have_lock_waits_table" ]; then @@ -1414,6 +1421,7 @@ stalk() { # Start collecting, maybe. # ################################################################## log "Collect $ITER triggered" + log "MYSQL_ONLY: $OPT_MYSQL_ONLY" # Send email to whomever that collect has been triggered. if [ "$OPT_NOTIFY_BY_EMAIL" ]; then @@ -1424,7 +1432,6 @@ stalk() { if [ "$OPT_COLLECT" ]; then local prefix="${OPT_PREFIX:-$(date +%F-%T | tr ':-' '_')}" - # Check if we'll have enough disk space to collect. Disk space # is also checked every interval while collecting. local margin="20971520" # default 20M margin, unless: @@ -2093,6 +2100,13 @@ Plugin writers should keep in mind that the file destination prefix currently in use should be accessed through the C<$prefix> variable, rather than C<$OPT_PREFIX>. +=item --mysql-only + +Trigger only MySQL related captures, ignoring all others. The only not MySQL related +value being collected is the disk space, because it is needed to calculate the +available free disk space to write the result files. +This option is useful for RDS instances. + =item --port short form: -P; type: int @@ -2362,7 +2376,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-stalk 3.0.6 +pt-stalk 3.0.7 =cut diff --git a/bin/pt-table-checksum b/bin/pt-table-checksum index c1f14786..67d4fccc 100755 --- a/bin/pt-table-checksum +++ b/bin/pt-table-checksum @@ -797,15 +797,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -1022,6 +1023,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -1058,7 +1099,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-table-sync b/bin/pt-table-sync index 67d3d6dc..0817e384 100755 --- a/bin/pt-table-sync +++ b/bin/pt-table-sync @@ -55,7 +55,7 @@ BEGIN { { package Percona::Toolkit; -our $VERSION = '3.0.6'; +our $VERSION = '3.0.7'; use strict; use warnings FATAL => 'all'; @@ -2137,6 +2137,7 @@ sub parse { } } + $self->{dsn_props} = \%final_props; return \%final_props; } @@ -2319,6 +2320,20 @@ sub get_dbh { } } + if ($self->{dsn_props}->{D} && $self->{dsn_props}->{t}) { + PTDEBUG && _d("DSN has a schema and table: $self->{dsn_props}->{D}.$self->{dsn_props}->{t}"); + PTDEBUG && _d("Trying to set the default charset for the connection"); + my (undef, $create_table) = eval { $dbh->selectrow_array("SHOW CREATE TABLE $self->{dsn_props}->{D}.$self->{dsn_props}->{t}") }; + + if ($create_table && $create_table =~ m/DEFAULT CHARSET=(\S+)\s*/) { + PTDEBUG && _d("Detected table's character set: $1"); + PTDEBUG && _d("Executing: SET NAMES '$1'"); + $dbh->do("SET NAMES '$1'"); + } else { + PTDEBUG && _d("Cannot get the default character set for the table"); + } + } + PTDEBUG && _d('DBH info: ', $dbh, Dumper($dbh->selectrow_hashref( @@ -9200,15 +9215,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -9425,6 +9441,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -9461,7 +9517,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { @@ -10644,6 +10700,16 @@ sub sync_a_table { : $tbl_struct->{engine} eq 'InnoDB' ? 1 : 0; + if ($tbl_struct->{charset}) { + PTDEBUG && _d("Detected table's character set: $tbl_struct->{charset}"); + PTDEBUG && _d("Executing: SET NAMES '$tbl_struct->{charset}'"); + $src->{dbh}->do("SET NAMES '$tbl_struct->{charset}'"); + $src->{misc_dbh}->do("SET NAMES '$tbl_struct->{charset}'"); + $dst->{dbh}->do("SET NAMES '$tbl_struct->{charset}'"); + $dst->{misc_dbh}->do("SET NAMES '$tbl_struct->{charset}'"); + } else { + PTDEBUG && _d("Cannot get the default character set for the table"); + } # Turn off AutoCommit if we're using transactions. $src->{dbh}->{AutoCommit} = !$use_txn; $src->{misc_dbh}->{AutoCommit} = !$use_txn; @@ -12977,6 +13043,6 @@ Place, Suite 330, Boston, MA 02111-1307 USA. =head1 VERSION -pt-table-sync 3.0.6 +pt-table-sync 3.0.7 =cut diff --git a/bin/pt-upgrade b/bin/pt-upgrade index c4753636..4e671878 100755 --- a/bin/pt-upgrade +++ b/bin/pt-upgrade @@ -4086,15 +4086,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -4311,6 +4312,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -4347,7 +4388,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/bin/pt-variable-advisor b/bin/pt-variable-advisor index ce80e9f2..e3aeb29e 100755 --- a/bin/pt-variable-advisor +++ b/bin/pt-variable-advisor @@ -4504,15 +4504,16 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -4729,6 +4730,46 @@ sub get_instance_id { } +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + + sub pingback { my (%args) = @_; my @required_args = qw(url instances); @@ -4765,7 +4806,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/config/deb/postinst b/config/deb/postinst new file mode 100644 index 00000000..836c6c91 --- /dev/null +++ b/config/deb/postinst @@ -0,0 +1,8 @@ +#!/bin/bash + +if [ ! -e /etc/percona-toolkit/.percona.toolkit.uuid ]; then + mkdir -p /etc/percona-toolkit + perl -e 'printf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7;' > /etc/percona-toolkit/.percona.toolkit.uuid +fi + +#DEBHELPER# diff --git a/config/rpm/percona-toolkit.spec b/config/rpm/percona-toolkit.spec index b2bddfc9..e19a673c 100644 --- a/config/rpm/percona-toolkit.spec +++ b/config/rpm/percona-toolkit.spec @@ -42,6 +42,11 @@ find $RPM_BUILD_ROOT -type f -name 'percona-toolkit.pod' -exec rm -f {} ';' rm -rf $RPM_BUILD_ROOT/usr/share/perl5 chmod -R u+w $RPM_BUILD_ROOT/* +%post +if [ ! -e /etc/percona-toolkit/.percona.toolkit.uuid ]; then + mkdir -p /etc/percona-toolkit + perl -e 'printf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7;' > /etc/percona-toolkit/.percona.toolkit.uuid +fi %clean rm -rf $RPM_BUILD_ROOT diff --git a/lib/VersionCheck.pm b/lib/VersionCheck.pm index 0c126d11..b612dd04 100644 --- a/lib/VersionCheck.pm +++ b/lib/VersionCheck.pm @@ -48,6 +48,14 @@ eval { require HTTP::Micro; }; +my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; +my @vc_dirs = ( + '/etc/percona', + '/etc/percona-toolkit', + '/tmp', + "$home", +); + # Return the version check file used to keep track of # MySQL instance that have been checked and when. Some # systems use random tmp dirs; we don't want that else @@ -55,13 +63,6 @@ eval { # per system is the goal, so prefer global sys dirs first. { my $file = 'percona-version-check'; - my $home = $ENV{HOME} || $ENV{HOMEPATH} || $ENV{USERPROFILE} || '.'; - my @vc_dirs = ( - '/etc/percona', - '/etc/percona-toolkit', - '/tmp', - "$home", - ); sub version_check_file { foreach my $dir ( @vc_dirs ) { @@ -326,6 +327,49 @@ sub get_instance_id { return $name, $id; } + +# This function has been implemented solely to be able to count individual +# Toolkit users for statistics. It uses a random UUID, no client info is +# being gathered nor stored +sub get_uuid { + my $uuid_file = '/.percona-toolkit.uuid'; + foreach my $dir (@vc_dirs) { + my $filename = $dir.$uuid_file; + my $uuid=_read_uuid($filename); + return $uuid if $uuid; + } + + my $filename = $ENV{"HOME"} . $uuid_file; + my $uuid = _generate_uuid(); + + open(my $fh, '>', $filename) or die "Could not open file '$filename' $!"; + print $fh $uuid; + close $fh; + + return $uuid; +} + +sub _generate_uuid { + return sprintf+($}="%04x")."$}-$}-$}-$}-".$}x3,map rand 65537,0..7; +} + +sub _read_uuid { + my $filename = shift; + my $fh; + + eval { + open($fh, '<:encoding(UTF-8)', $filename); + }; + return if ($EVAL_ERROR); + + my $uuid; + eval { $uuid = <$fh>; }; + return if ($EVAL_ERROR); + + chomp $uuid; + return $uuid; +} + # ############################################################################# # Protocol handlers # ############################################################################# @@ -387,7 +431,7 @@ sub pingback { my $client_content = encode_client_response( items => $items, versions => $versions, - general_id => md5_hex( hostname() ), + general_id => get_uuid(), ); my $client_response = { diff --git a/lib/bash/collect.sh b/lib/bash/collect.sh index ba0ca6a3..92dedae2 100644 --- a/lib/bash/collect.sh +++ b/lib/bash/collect.sh @@ -49,8 +49,11 @@ collect() { local d="$1" # directory to save results in local p="$2" # prefix for each result file + local mysqld_pid="" # Get pidof mysqld. - local mysqld_pid=$(_pidof mysqld | awk '{print $1; exit;}') + if [ ! "$OPT_MYSQL_ONLY" ]; then + mysqld_pid=$(_pidof mysqld | awk '{print $1; exit;}') + fi # Get memory allocation info before anything else. if [ "$CMD_PMAP" -a "$mysqld_pid" ]; then @@ -90,7 +93,7 @@ collect() { fi local tail_error_log_pid="" - if [ "$mysql_error_log" ]; then + if [ "$mysql_error_log" -a ! "$OPT_MYSQL_ONLY" ]; then log "The MySQL error log seems to be $mysql_error_log" tail -f "$mysql_error_log" >"$d/$p-log_error" & tail_error_log_pid=$! @@ -141,44 +144,46 @@ collect() { # Grab a few general things first. Background all of these so we can start # them all up as quickly as possible. - ps -eaF >> "$d/$p-ps" & - top -bn${OPT_RUN_TIME} >> "$d/$p-top" & + if [ ! "$OPT_MYSQL_ONLY" ]; then + ps -eaF >> "$d/$p-ps" & + top -bn${OPT_RUN_TIME} >> "$d/$p-top" & - [ "$mysqld_pid" ] && _lsof $mysqld_pid >> "$d/$p-lsof" & + [ "$mysqld_pid" ] && _lsof $mysqld_pid >> "$d/$p-lsof" & - if [ "$CMD_SYSCTL" ]; then - $CMD_SYSCTL -a >> "$d/$p-sysctl" & - fi + if [ "$CMD_SYSCTL" ]; then + $CMD_SYSCTL -a >> "$d/$p-sysctl" & + fi - # collect dmesg events from 60 seconds ago until present - if [ "$CMD_DMESG" ]; then - local UPTIME=`cat /proc/uptime | awk '{ print $1 }'` - local START_TIME=$(echo "$UPTIME 60" | awk '{print ($1 - $2)}') - $CMD_DMESG | perl -ne 'm/\[\s*(\d+)\./; if ($1 > '${START_TIME}') { print }' >> "$d/$p-dmesg" & - fi + # collect dmesg events from 60 seconds ago until present + if [ "$CMD_DMESG" ]; then + local UPTIME=`cat /proc/uptime | awk '{ print $1 }'` + local START_TIME=$(echo "$UPTIME 60" | awk '{print ($1 - $2)}') + $CMD_DMESG | perl -ne 'm/\[\s*(\d+)\./; if ($1 > '${START_TIME}') { print }' >> "$d/$p-dmesg" & + fi - local cnt=$(($OPT_RUN_TIME / $OPT_SLEEP_COLLECT)) - if [ "$CMD_VMSTAT" ]; then - $CMD_VMSTAT $OPT_SLEEP_COLLECT $cnt >> "$d/$p-vmstat" & - $CMD_VMSTAT $OPT_RUN_TIME 2 >> "$d/$p-vmstat-overall" & - fi - if [ "$CMD_IOSTAT" ]; then - $CMD_IOSTAT -dx $OPT_SLEEP_COLLECT $cnt >> "$d/$p-iostat" & - $CMD_IOSTAT -dx $OPT_RUN_TIME 2 >> "$d/$p-iostat-overall" & - fi - if [ "$CMD_MPSTAT" ]; then - $CMD_MPSTAT -P ALL $OPT_SLEEP_COLLECT $cnt >> "$d/$p-mpstat" & - $CMD_MPSTAT -P ALL $OPT_RUN_TIME 1 >> "$d/$p-mpstat-overall" & - fi + local cnt=$(($OPT_RUN_TIME / $OPT_SLEEP_COLLECT)) + if [ "$CMD_VMSTAT" ]; then + $CMD_VMSTAT $OPT_SLEEP_COLLECT $cnt >> "$d/$p-vmstat" & + $CMD_VMSTAT $OPT_RUN_TIME 2 >> "$d/$p-vmstat-overall" & + fi + if [ "$CMD_IOSTAT" ]; then + $CMD_IOSTAT -dx $OPT_SLEEP_COLLECT $cnt >> "$d/$p-iostat" & + $CMD_IOSTAT -dx $OPT_RUN_TIME 2 >> "$d/$p-iostat-overall" & + fi + if [ "$CMD_MPSTAT" ]; then + $CMD_MPSTAT -P ALL $OPT_SLEEP_COLLECT $cnt >> "$d/$p-mpstat" & + $CMD_MPSTAT -P ALL $OPT_RUN_TIME 1 >> "$d/$p-mpstat-overall" & + fi - # Collect multiple snapshots of the status variables. We use - # mysqladmin -c even though it is buggy and won't stop on its - # own in 5.1 and newer, because there is a chance that we will - # get and keep a connection to the database; in troubled times - # the database tends to exceed max_connections, so reconnecting - # in the loop tends not to work very well. - $CMD_MYSQLADMIN $EXT_ARGV ext -i$OPT_SLEEP_COLLECT -c$cnt >>"$d/$p-mysqladmin" & - local mysqladmin_pid=$! + # Collect multiple snapshots of the status variables. We use + # mysqladmin -c even though it is buggy and won't stop on its + # own in 5.1 and newer, because there is a chance that we will + # get and keep a connection to the database; in troubled times + # the database tends to exceed max_connections, so reconnecting + # in the loop tends not to work very well. + $CMD_MYSQLADMIN $EXT_ARGV ext -i$OPT_SLEEP_COLLECT -c$cnt >>"$d/$p-mysqladmin" & + local mysqladmin_pid=$! + fi local have_lock_waits_table="" $CMD_MYSQL $EXT_ARGV -e "SHOW TABLES FROM INFORMATION_SCHEMA" \ @@ -200,47 +205,48 @@ collect() { fi while [ $((curr_time - start_time)) -lt $OPT_RUN_TIME ]; do + if [ ! "$OPT_MYSQL_ONLY" ]; then + # We check the disk, but don't exit, because we need to stop jobs if we + # need to exit. + disk_space $d > $d/$p-disk-space + check_disk_space \ + $d/$p-disk-space \ + "$OPT_DISK_BYTES_FREE" \ + "$OPT_DISK_PCT_FREE" \ + || break - # We check the disk, but don't exit, because we need to stop jobs if we - # need to exit. - disk_space $d > $d/$p-disk-space - check_disk_space \ - $d/$p-disk-space \ - "$OPT_DISK_BYTES_FREE" \ - "$OPT_DISK_PCT_FREE" \ - || break + # Sleep between collect cycles. + # Synchronize ourselves onto the clock tick, so the sleeps are 1-second + sleep $(date +'%s.%N' | awk "{print $OPT_SLEEP_COLLECT - (\$1 % $OPT_SLEEP_COLLECT)}") + local ts="$(date +"TS %s.%N %F %T")" - # Sleep between collect cycles. - # Synchronize ourselves onto the clock tick, so the sleeps are 1-second - sleep $(date +'%s.%N' | awk "{print $OPT_SLEEP_COLLECT - (\$1 % $OPT_SLEEP_COLLECT)}") - local ts="$(date +"TS %s.%N %F %T")" - - # ##################################################################### - # Collect data for this cycle. - # ##################################################################### - if [ -d "/proc" ]; then - if [ -f "/proc/diskstats" ]; then - (echo $ts; cat /proc/diskstats) >> "$d/$p-diskstats" & - fi - if [ -f "/proc/stat" ]; then - (echo $ts; cat /proc/stat) >> "$d/$p-procstat" & - fi - if [ -f "/proc/vmstat" ]; then - (echo $ts; cat /proc/vmstat) >> "$d/$p-procvmstat" & - fi - if [ -f "/proc/meminfo" ]; then - (echo $ts; cat /proc/meminfo) >> "$d/$p-meminfo" & - fi - if [ -f "/proc/slabinfo" ]; then - (echo $ts; cat /proc/slabinfo) >> "$d/$p-slabinfo" & - fi - if [ -f "/proc/interrupts" ]; then - (echo $ts; cat /proc/interrupts) >> "$d/$p-interrupts" & + # ##################################################################### + # Collect data for this cycle. + # ##################################################################### + if [ -d "/proc" ]; then + if [ -f "/proc/diskstats" ]; then + (echo $ts; cat /proc/diskstats) >> "$d/$p-diskstats" & + fi + if [ -f "/proc/stat" ]; then + (echo $ts; cat /proc/stat) >> "$d/$p-procstat" & + fi + if [ -f "/proc/vmstat" ]; then + (echo $ts; cat /proc/vmstat) >> "$d/$p-procvmstat" & + fi + if [ -f "/proc/meminfo" ]; then + (echo $ts; cat /proc/meminfo) >> "$d/$p-meminfo" & + fi + if [ -f "/proc/slabinfo" ]; then + (echo $ts; cat /proc/slabinfo) >> "$d/$p-slabinfo" & + fi + if [ -f "/proc/interrupts" ]; then + (echo $ts; cat /proc/interrupts) >> "$d/$p-interrupts" & + fi fi + (echo $ts; df -k) >> "$d/$p-df" & + (echo $ts; netstat -antp) >> "$d/$p-netstat" & + (echo $ts; netstat -s) >> "$d/$p-netstat_s" & fi - (echo $ts; df -k) >> "$d/$p-df" & - (echo $ts; netstat -antp) >> "$d/$p-netstat" & - (echo $ts; netstat -s) >> "$d/$p-netstat_s" & (echo $ts; $CMD_MYSQL $EXT_ARGV -e "SHOW FULL PROCESSLIST\G") \ >> "$d/$p-processlist" & if [ "$have_lock_waits_table" ]; then diff --git a/sandbox/servers/5.7/my.sandbox.cnf b/sandbox/servers/5.7/my.sandbox.cnf index 881ea914..a3cf5c9b 100644 --- a/sandbox/servers/5.7/my.sandbox.cnf +++ b/sandbox/servers/5.7/my.sandbox.cnf @@ -27,6 +27,7 @@ innodb_lock_wait_timeout = 3 general_log general_log_file = genlog lower_case_table_names = 0 +#character-set-server = utf8 # fkc test binlog_format = STATEMENT diff --git a/t/lib/VersionCheck.t b/t/lib/VersionCheck.t index ba9881a5..30436a68 100644 --- a/t/lib/VersionCheck.t +++ b/t/lib/VersionCheck.t @@ -201,7 +201,7 @@ is_deeply( # Former Pingback tests # ############################################################################# -my $general_id = md5_hex( hostname() ); +my $general_id = VersionCheck::get_uuid(); my $master_id; # the instance ID, _not_ 12345 etc. my $slave1_id; # the instance ID, _not_ 12346 etc. my ($mysql_ver, $mysql_distro); @@ -679,6 +679,22 @@ foreach my $tool ( @vc_tools ) { ); } +my $should_remove_uuid_file; +my $home_uuid_file = $ENV{"HOME"} . "/.percona-toolkit.uuid"; + +if ( ! -e $home_uuid_file ) { + $should_remove_uuid_file = 1; +} + +my $uuid = VersionCheck::get_uuid(); +is ( + length($uuid), + 36, + "Have a valid UUID4", +); + +unlink $home_uuid_file if $should_remove_uuid_file; + # ############################################################################# # Done. # ############################################################################# diff --git a/t/lib/samples/charset.sql b/t/lib/samples/charset.sql new file mode 100644 index 00000000..a2a03af4 --- /dev/null +++ b/t/lib/samples/charset.sql @@ -0,0 +1,15 @@ +DROP DATABASE IF EXISTS `test`; +CREATE DATABASE `test`; + +CREATE TABLE `test`.`t1` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `f2` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`) +) COMMENT "test1" ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE `test`.`t2` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `f2` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + diff --git a/t/pt-table-sync/pt-1256.t b/t/pt-table-sync/pt-1256.t new file mode 100644 index 00000000..04c34f8c --- /dev/null +++ b/t/pt-table-sync/pt-1256.t @@ -0,0 +1,97 @@ +#!/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 utf8; +use Encode qw(decode encode); +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use Test::More; + +use PerconaTest; +use Sandbox; +require "$trunk/bin/pt-table-sync"; + +binmode(STDIN, ':utf8') or die "Can't binmode(STDIN, ':utf8'): $OS_ERROR"; +binmode(STDOUT, ':utf8') or die "Can't binmode(STDOUT, ':utf8'): $OS_ERROR"; + +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'); +my $slave2_dbh = $sb->get_dbh_for('slave2'); + +if ( !$master_dbh ) { + plan skip_all => 'Cannot connect to sandbox master'; +} +elsif ( !$slave1_dbh ) { + plan skip_all => 'Cannot connect to sandbox slave1'; +} +elsif ( !$slave1_dbh ) { + plan skip_all => 'Cannot connect to sandbox slave2'; +} +else { + plan tests => 5; +} + +my ($output, $status); +my @args = ('--sync-to-master', 'h=127.1,P=12346,u=msandbox,p=msandbox', + qw(-t test.t1 --print --execute)); + +# use lib/samples dir since the main change is in DSNParser +$sb->load_file('master', "t/lib/samples/charset.sql"); + +my $want = encode('UTF-8','абвгд'); + +$master_dbh->do("SET NAMES 'utf8'"); +$slave1_dbh->do("SET NAMES 'utf8'"); +$slave1_dbh->do("SET NAMES 'utf8'"); + +$master_dbh->do("INSERT INTO test.t1 VALUES (NULL, '$want')"); +$sb->wait_for_slaves(); + +$slave1_dbh->do("DELETE FROM test.t1 WHERE id=1 LIMIT 1"); +$slave1_dbh->do("FLUSH TABLES"); + + +# 1 +($output, $status) = full_output( + sub { pt_table_sync::main(@args) }, +); + +like( + $output, + qr/REPLACE INTO `test`.`t1`/, + "PT-1256 Set the correct charset" +); + +# 2 +my $row = $slave1_dbh->selectrow_hashref("SELECT f2 FROM test.t1 WHERE id = 1"); +is( + $row->{f2}, + $want, + "Character set is correct", +); + +# 3 +$output = `$trunk/bin/pt-table-sync --execute --lock-and-rename h=127.1,P=12345,u=msandbox,p=msandbox,D=test,t=t1 t=t2 2>&1`; +$output = `/tmp/12345/use -e 'show create table test.t2'`; +like($output, qr/COMMENT='test1'/, '--lock-and-rename worked'); + +$row = $slave1_dbh->selectrow_hashref("SELECT f2 FROM test.t2 WHERE id = 1"); +is( + $row->{f2}, + $want, + "Character set is correct", +); +# ############################################################################# +# Done. +# ############################################################################# +$sb->wipe_clean($master_dbh); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +exit;