diff --git a/bin/pt-online-schema-change b/bin/pt-online-schema-change index 706c072e..1f85ce14 100755 --- a/bin/pt-online-schema-change +++ b/bin/pt-online-schema-change @@ -8169,6 +8169,8 @@ sub main { # ######################################################################## # Init the --plugin. # ######################################################################## + + # --plugin hook if ( $plugin && $plugin->can('init') ) { $plugin->init( orig_tbl => $orig_tbl, @@ -10168,9 +10170,10 @@ server. See L<"--max-load"> and L<"--critical-load"> for details. =item * -The tool sets its lock wait timeout to 1 second so that it is more likely to be -the victim of any lock contention, and less likely to disrupt other -transactions. See L<"--lock-wait-timeout"> for details. +The tool sets C and (for MySQL 5.5 and newer) +C so that it is more likely to be the victim of any +lock contention, and less likely to disrupt other transactions. These +values can be changed by specifying L<"--set-vars">. =item * @@ -10705,8 +10708,13 @@ removed automatically when the tool exits. type: string -Use the given Perl module to access hooks in the tool. -C must be defined in the file. +Perl module file that defines a C class. +A plugin allows you to write a Perl module that can hook into many parts +of pt-online-schema-change. This requires a good knowledge of Perl and +Percona Toolkit conventions, which are beyond this scope of this +documentation. Please contact Percona if you have questions or need help. + +See L<"PLUGIN"> for more information. =item --port @@ -10862,6 +10870,52 @@ For more information, visit L. =back +=head1 PLUGIN + +The file specified by L<"--plugin"> must define a class (i.e. a package) +called C with a C subroutine. +The tool will create an instance of this class and call any hooks that +it defines. No hooks are required, but a plugin isn't very useful without +them. + +These hooks, in this order, are called if defined: + + init + before_create_new_table + after_create_new_table + before_alter_new_table + after_alter_new_table + before_create_triggers + after_create_triggers + before_copy_rows + after_copy_rows + before_swap_tables + after_swap_tables + before_update_foreign_keys + after_update_foreign_keys + before_drop_old_table + after_drop_old_table + before_drop_triggers + before_exit + +Each hook is passed different arguments. To see which arguments are passed +to a hook, search for the hook's name in the tool's source code, like: + + # --plugin hook + if ( $plugin && $plugin->can('init') ) { + $plugin->init( + orig_tbl => $orig_tbl, + child_tables => $child_tables, + renamed_cols => $renamed_cols, + slaves => $slaves, + slave_lag_cxns => $slave_lag_cxns, + ); + } + +The comment C<# --plugin hook> precedes every hook call. + +Please contact Percona if you have questions or need help. + =head1 DSN OPTIONS These DSN options are used to create a DSN. Each option is given like diff --git a/t/pt-online-schema-change/plugin.t b/t/pt-online-schema-change/plugin.t new file mode 100644 index 00000000..1be15200 --- /dev/null +++ b/t/pt-online-schema-change/plugin.t @@ -0,0 +1,83 @@ +#!/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; +use Sandbox; +require "$trunk/bin/pt-online-schema-change"; + +use Data::Dumper; +$Data::Dumper::Indent = 1; +$Data::Dumper::Sortkeys = 1; +$Data::Dumper::Quotekeys = 0; + +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 $output; +my $master_dsn = $sb->dsn_for('master'); +my $sample = "t/pt-online-schema-change/samples"; +my $plugin = "$trunk/$sample/plugins"; +my $exit; +my $rows; + +# Loads pt_osc.t with cols id (pk), c (unique index),, d. +$sb->load_file('master', "$sample/basic_no_fks_innodb.sql"); + +# ############################################################################# +# all_hooks.pm +# ############################################################################# + +($output) = full_output( + sub { pt_online_schema_change::main( + "$master_dsn,D=pt_osc,t=t", + '--plugin', "$plugin/all_hooks.pm", + qw(--statistics --execute), + )}, + stderr => 1, +); + +my @called = $output =~ m/^PLUGIN \S+$/gm; + +is_deeply( + \@called, + [ + 'PLUGIN init', + 'PLUGIN before_create_new_table', + 'PLUGIN after_create_new_table', + 'PLUGIN before_alter_new_table', + 'PLUGIN after_alter_new_table', + 'PLUGIN before_create_triggers', + 'PLUGIN after_create_triggers', + 'PLUGIN before_copy_rows', + 'PLUGIN after_copy_rows', + 'PLUGIN before_swap_tables', + 'PLUGIN after_swap_tables', + 'PLUGIN before_drop_old_table', + 'PLUGIN after_drop_old_table', + 'PLUGIN before_drop_triggers', + 'PLUGIN before_exit' + ], + "Called all plugins on basic run" +) or diag(Dumper(\@called)); + +# ############################################################################# +# Done. +# ############################################################################# +$sb->wipe_clean($dbh); +ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox"); +done_testing; diff --git a/t/pt-online-schema-change/samples/plugins/all_hooks.pm b/t/pt-online-schema-change/samples/plugins/all_hooks.pm new file mode 100644 index 00000000..f629fc51 --- /dev/null +++ b/t/pt-online-schema-change/samples/plugins/all_hooks.pm @@ -0,0 +1,99 @@ +package pt_online_schema_change_plugin; + +use strict; +use warnings FATAL => 'all'; +use English qw(-no_match_vars); +use constant PTDEBUG => $ENV{PTDEBUG} || 0; + +sub new { + my ($class, %args) = @_; + my $self = { %args }; + return bless $self, $class; +} + +sub init { + my ($self, %args) = @_; + print "PLUGIN init\n"; +} + +sub before_create_new_table { + my ($self, %args) = @_; + print "PLUGIN before_create_new_table\n"; +} + +sub after_create_new_table { + my ($self, %args) = @_; + print "PLUGIN after_create_new_table\n"; +} + +sub before_alter_new_table { + my ($self, %args) = @_; + print "PLUGIN before_alter_new_table\n"; +} + +sub after_alter_new_table { + my ($self, %args) = @_; + print "PLUGIN after_alter_new_table\n"; +} + +sub before_create_triggers { + my ($self, %args) = @_; + print "PLUGIN before_create_triggers\n"; +} + +sub after_create_triggers { + my ($self, %args) = @_; + print "PLUGIN after_create_triggers\n"; +} + +sub before_copy_rows { + my ($self, %args) = @_; + print "PLUGIN before_copy_rows\n"; +} + +sub after_copy_rows { + my ($self, %args) = @_; + print "PLUGIN after_copy_rows\n"; +} + +sub before_swap_tables { + my ($self, %args) = @_; + print "PLUGIN before_swap_tables\n"; +} + +sub after_swap_tables { + my ($self, %args) = @_; + print "PLUGIN after_swap_tables\n"; +} + +sub before_update_foreign_keys { + my ($self, %args) = @_; + print "PLUGIN before_update_foreign_keys\n"; +} + +sub after_update_foreign_keys { + my ($self, %args) = @_; + print "PLUGIN after_update_foreign_keys\n"; +} + +sub before_drop_old_table { + my ($self, %args) = @_; + print "PLUGIN before_drop_old_table\n"; +} + +sub after_drop_old_table { + my ($self, %args) = @_; + print "PLUGIN after_drop_old_table\n"; +} + +sub before_drop_triggers { + my ($self, %args) = @_; + print "PLUGIN before_drop_triggers\n"; +} + +sub before_exit { + my ($self, %args) = @_; + print "PLUGIN before_exit\n"; +} + +1;