From f200fa15db3c39639c6467ab114dbff9dc8ff8be Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Jul 2003 16:03:29 +0200 Subject: Fix for BUG#812 "mysqlhotcopy fails to copy tables but does not indicate a failure" ("does not indicate a failure"); this is about "mysqlhotcopy fails to copy tables". mysql-test/t/rpl_error_ignored_table-slave.opt: added a missing newline scripts/mysqlhotcopy.sh: Fix for BUG#812. The problem was that with many tables to copy (10000 in the bug's example), the generated 'cp' command line was 1MB long, whereas (at least on my Linux) it should not exceed 128 kB. Testing the 'cp' in a shell terminal gives "arguments list too long". So we issue several small (100 kB) 'cp' command lines instead of a big one. Of course, this will still fail on systems where the limit is below 100 kB. We now have safe_system() which cuts the command line in pieces, and calls safe_simple_system() (execution) for each piece. --- mysql-test/t/rpl_error_ignored_table-slave.opt | 2 +- scripts/mysqlhotcopy.sh | 70 ++++++++++++++++++-------- 2 files changed, 50 insertions(+), 22 deletions(-) diff --git a/mysql-test/t/rpl_error_ignored_table-slave.opt b/mysql-test/t/rpl_error_ignored_table-slave.opt index 544ecb2959b..0d3485f9e25 100644 --- a/mysql-test/t/rpl_error_ignored_table-slave.opt +++ b/mysql-test/t/rpl_error_ignored_table-slave.opt @@ -1 +1 @@ ---replicate-ignore-table=test.t1 \ No newline at end of file +--replicate-ignore-table=test.t1 diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 98a5c5b9f85..f23955da06a 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -569,22 +569,22 @@ sub copy_files { print "Copying ".@$files." files...\n" unless $opt{quiet}; if ($method =~ /^s?cp\b/) { # cp or scp with optional flags - my @cp = ($method); + my $cp = $method; # add option to preserve mod time etc of copied files # not critical, but nice to have - push @cp, "-p" if $^O =~ m/^(solaris|linux|freebsd|darwin)$/; + $cp.= " -p" if $^O =~ m/^(solaris|linux|freebsd|darwin)$/; # add recursive option for scp - push @cp, "-r" if $^O =~ /m^(solaris|linux|freebsd|darwin)$/ && $method =~ /^scp\b/; + $cp.= " -r" if $^O =~ /m^(solaris|linux|freebsd|darwin)$/ && $method =~ /^scp\b/; my @non_raid = map { "'$_'" } grep { ! m:/\d{2}/[^/]+$: } @$files; # add files to copy and the destination directory - safe_system( @cp, @non_raid, "'$target'" ) if (@non_raid); + safe_system( $cp, @non_raid, "'$target'" ) if (@non_raid); foreach my $rd ( @$raid_dirs ) { my @raid = map { "'$_'" } grep { m:$rd/: } @$files; - safe_system( @cp, @raid, "'$target'/$rd" ) if ( @raid ); + safe_system( $cp, @raid, "'$target'/$rd" ) if ( @raid ); } } else @@ -646,26 +646,54 @@ sub copy_index } -sub safe_system -{ - my @cmd= @_; - - if ( $opt{dryrun} ) - { - print "@cmd\n"; - return; +sub safe_system { + my @sources= @_; + my $method= shift @sources; + my $target= pop @sources; + ## @sources = list of source file names + + ## We have to deal with very long command lines, otherwise they may generate + ## "Argument list too long". + ## With 10000 tables the command line can be around 1MB, much more than 128kB + ## which is the common limit on Linux (can be read from + ## /usr/src/linux/include/linux/binfmts.h + ## see http://www.linuxjournal.com/article.php?sid=6060). + + my $chunk_limit= 100 * 1024; # 100 kB + my @chunk= (); + my $chunk_length= 0; + foreach (@sources) { + push @chunk, $_; + $chunk_length+= length($_); + if ($chunk_length > $chunk_limit) { + safe_simple_system($method, @chunk, $target); + @chunk=(); + $chunk_length= 0; + } } - - ## for some reason system fails but backticks works ok for scp... - print "Executing '@cmd'\n" if $opt{debug}; - my $cp_status = system "@cmd > /dev/null"; - if ($cp_status != 0) { - warn "Executing command failed ($cp_status). Trying backtick execution...\n"; - ## try something else - `@cmd` || die "Error: @cmd failed ($?) while copying files.\n"; + if ($chunk_length > 0) { # do not forget last small chunk + safe_simple_system($method, @chunk, $target); } } +sub safe_simple_system { + my @cmd= @_; + + if ( $opt{dryrun} ) { + print "@cmd\n"; + } + else { + ## for some reason system fails but backticks works ok for scp... + print "Executing '@cmd'\n" if $opt{debug}; + my $cp_status = system "@cmd > /dev/null"; + if ($cp_status != 0) { + warn "Executing command failed ($cp_status). Trying backtick execution...\n"; + ## try something else + `@cmd` || die "Error: @cmd failed ($?) while copying files.\n"; + } + } +} + sub retire_directory { my ( @dir ) = @_; -- cgit v1.2.1