diff options
-rwxr-xr-x | checksetup.pl | 19 | ||||
-rwxr-xr-x | syncshadowdb | 95 |
2 files changed, 107 insertions, 7 deletions
diff --git a/checksetup.pl b/checksetup.pl index 7c165b9eb..053adc192 100755 --- a/checksetup.pl +++ b/checksetup.pl @@ -283,6 +283,25 @@ sub LocalVar ($$) # Set up the defaults for the --LOCAL-- variables below: # +my $mysql_binaries = `which mysql`; +if ($mysql_binaries =~ /no mysql/) { + # If which didn't find it, just provide a reasonable default + $mysql_binaries = "/usr/bin"; +} else { + $mysql_binaries =~ s:/mysql\n$::; +} + +LocalVar('mysqlpath', <<"END"); +# +# In order to do certain functions in Bugzilla (such as sync the shadow +# database), we require the MySQL Binaries (mysql, mysqldump, and mysqladmin). +# Because it's possible that these files aren't in your path, you can specify +# their location here. +# Please specify only the directory name, with no trailing slash. +\$mysqlpath = "$mysql_binaries"; +END + + LocalVar('create_htaccess', <<'END'); # # If you are using Apache for your web server, Bugzilla can create .htaccess diff --git a/syncshadowdb b/syncshadowdb index 4733dbb58..b60807a99 100755 --- a/syncshadowdb +++ b/syncshadowdb @@ -39,18 +39,35 @@ sub sillyness { my $verbose = 0; my $syncall = 0; +my $shutdown = 0; +my $tempdir = "data"; +my $force = 0; + +my $shutdown_msg = "Bugzilla is temporarily disabled while the database is backed up. Try again in a few minutes."; sub Usage { - print "Usage: syncshadowdb [-v] [-syncall]\n"; + print "Usage: syncshadowdb [-v] [-syncall] [-shutdown] [-tempdir dirname] [-force]\n"; exit; } -foreach my $opt (@ARGV) { +while (my $opt = shift @ARGV) { if ($opt eq '-v') { $verbose = 1; } elsif ($opt eq '-syncall') { $syncall = 1; $verbose = 1; + } elsif ($opt eq '-shutdown') { + $shutdown = 1; + } elsif ($opt eq '-tempdir') { + my $dir = shift @ARGV; + if (-d $dir) { + $tempdir = $dir; + } else { + print "$dir does not exist or is not a directory. No syncing performed"; + exit; + } + } elsif ($opt eq '-force') { + $force = 1; } elsif ($opt eq '--') { # do nothing - null parameter so we can use # multi-param system() call in globals.pl @@ -78,6 +95,63 @@ if (!Param("shadowdb")) { exit; } +if (Param("shutdownhtml") && ! $force) { + Verbose("Bugzilla was shutdown prior to running syncshadowdb. \n" . + " If you wish to sync anyway, use the -force command line option"); + exit; +} + +my $wasshutdown = ""; +if ($shutdown) { + Verbose ("Shutting down bugzilla and waiting for connections to clear"); + # Record the old shutdownhtml so it can be restored at the end (this will + # only be an issue if we are called using the -force comand line param) + $wasshutdown = Param("shutdownhtml"); + $::param{'shutdownhtml'} = $shutdown_msg; + WriteParams(); + # Now we need to wait for existing connections to this database to clear. We + # do this by looking for connections to the main or shadow database using + # 'mysqladmin processlist' + my $cmd = "$::mysqlpath/mysqladmin -u $::db_user"; + if ($::db_pass) { $cmd .= " -p$::db_pass" } + $cmd .= " processlist"; + my $found_proc = 1; + # We need to put together a nice little regular expression to use in the + # following loop that'll tell us if the return from mysqladmin contains + # either the main or shadow database. + my @dbs = ($::db_name, Param("shadowdb")); + my $db_expr = "^\\s*(" . join ("\|", @dbs) . ")\\s*\$"; + # Don't let this thing wait forever... + my $starttime = time(); + while ($found_proc) { + $found_proc = 0; + open (PROC, $cmd . "|"); + my @output = <PROC>; + close (PROC); + foreach my $line(@output) { + my @info = split (/\|/, $line); + # Ignore any line that doesn't have 9 pieces of info + # or contain Id (pretty printing crap) + if ($#info != 9 || $line =~ /Id/) { next } + if ($info[4] =~ m/$db_expr/) { + $found_proc = 1; + } + } + # If there are still active connections to Bugzilla 10 minutes after + # shutting it down, then something is wrong. + if ((time() - $starttime) > 600) { + # There should be a better way to notify the admin of something bad like + # this happening. + Verbose ("*** Waited for 10 minutes and there were still active \n" . + " connections to the bugzilla database. Giving up."); + $::param{'shutdownhtml'} = $wasshutdown; + WriteParams(); + exit; + } + } +} + + my $wasusing = Param("queryagainstshadowdb"); $::param{'queryagainstshadowdb'} = 1; # Force us to be able to use the @@ -114,8 +188,10 @@ if ($syncall) { if ($wasusing) { $::param{'queryagainstshadowdb'} = 0; WriteParams(); - Verbose("Disabled reading from the shadowdb. Sleeping 10 seconds to let other procs catch up."); - sleep(10); + if (! $shutdown) { + Verbose("Disabled reading from the shadowdb. Sleeping 10 seconds to let other procs catch up."); + sleep(10); + } $::param{'queryagainstshadowdb'} = 1; } my @tables; @@ -157,7 +233,7 @@ if ($syncall) { } Verbose("Locking entire database"); SendSQL($query); - my $tempfile = "data/tmpsyncshadow.$$"; + my $tempfile = "$tempdir/tmpsyncshadow.$$"; Verbose("Dumping database to a temp file ($tempfile)."); my @ARGS = ("-u", $::db_user); if ($::db_pass) { push @ARGS, "-p$::db_pass" } @@ -165,7 +241,7 @@ if ($syncall) { open SAVEOUT, ">&STDOUT"; # stash the original output stream open STDOUT, ">$tempfile"; # redirect to file select STDOUT; $| = 1; # disable buffering - system("mysqldump", @ARGS); + system("$::mysqlpath/mysqldump", @ARGS); open STDOUT, ">&SAVEOUT"; # redirect back to original stream Verbose("Restoring from tempfile into shadowdb"); my $extra = "-u $::db_user"; @@ -175,7 +251,7 @@ if ($syncall) { if ($verbose) { $extra .= " -v"; } - open(MYSQL, "cat $tempfile | mysql $extra " . + open(MYSQL, "cat $tempfile | $::mysqlpath/mysql $extra " . Param("shadowdb") . "|") || die "Couldn't do db copy"; my $count = 0; while (<MYSQL>) { @@ -199,6 +275,11 @@ if ($syncall) { $::param{'queryagainstshadowdb'} = 1; WriteParams(); } + if ($shutdown) { + Verbose("Restoring the original shutdown message (if any)"); + $::param{'shutdownhtml'} = $wasshutdown; + WriteParams(); + } Verbose("OK, done."); } |