diff options
Diffstat (limited to 'syncshadowdb')
-rwxr-xr-x | syncshadowdb | 327 |
1 files changed, 0 insertions, 327 deletions
diff --git a/syncshadowdb b/syncshadowdb deleted file mode 100755 index 23d53a6f3..000000000 --- a/syncshadowdb +++ /dev/null @@ -1,327 +0,0 @@ -#!/usr/bonsaitools/bin/perl -w -# -*- Mode: perl; indent-tabs-mode: nil -*- -# -# The contents of this file are subject to the Mozilla Public -# License Version 1.1 (the "License"); you may not use this file -# except in compliance with the License. You may obtain a copy of -# the License at http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS -# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or -# implied. See the License for the specific language governing -# rights and limitations under the License. -# -# The Original Code is the Bugzilla Bug Tracking System. -# -# The Initial Developer of the Original Code is Netscape Communications -# Corporation. Portions created by Netscape are -# Copyright (C) 1998 Netscape Communications Corporation. All -# Rights Reserved. -# -# Contributor(s): Terry Weissman <terry@mozilla.org> -# David Gardiner <david.gardiner@unisa.edu.au> - -use strict; - -use lib qw(.); - -use Bugzilla::Config qw(:DEFAULT :admin); - -require "globals.pl"; -require "defparams.pl"; - -# Shut up misguided -w warnings about "used only once". "use vars" just -# doesn't work for me. - -sub sillyness { - my $zz; - open SAVEOUT,">/dev/null"; - $zz = $::db; - $zz = $::dbwritesallowed; - $zz = $::db_host; - $zz = $::db_port; -} - -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] [-shutdown] [-tempdir dirname] [-force]\n"; - exit; -} - -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 - } else { - Usage(); - } -} -$| = 1; - -my $logtostderr = 0; - -sub Verbose ($) { - my ($str) = (@_); - if ($verbose) { - if ($logtostderr) { - print STDERR $str, "\n"; - } else { - print $str, "\n"; - } - } -} - -if (!Param("shadowdb")) { - Verbose("We don't have shadow databases turned on; no syncing performed."); - exit; -} - -if (!Param("updateshadowdb")) { - Verbose("This shadow database is not set to be updated by Bugzilla.\nSee the mysql replication FAQ if you want to pause the main db until the\nshadowdb catches up"); - # I could run the commands here, but that involves keeping a connection - # open to the main db and the shadowdb at the same time, and our current - # db stuff doesn't support that. Its not sufficient to reconnect, because - # the lock on the main db will be dropped when the connection closes... - exit 1; -} - -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 command line param) - $wasshutdown = Param("shutdownhtml"); - SetParam('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 -h $::db_host -P $::db_port"; - if ($::db_pass) { $cmd .= " -p$::db_pass"; } - if ($::db_sock) { $cmd .= " -S$::db_sock"; } - $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."); - SetParam('shutdownhtml', $wasshutdown); - WriteParams(); - exit; - } - } -} - - -my $wasusing = Param("queryagainstshadowdb"); - -SetParam('queryagainstshadowdb', 1); # Force us to be able to use the - # shadowdb, even if other processes - # are not supposed to. - - -ConnectToDatabase(1); - -Verbose("Acquiring lock"); -if ( $syncall == 1) { - SendSQL("SELECT GET_LOCK('synclock', 2700)"); -} else { - SendSQL("SELECT GET_LOCK('synclock', 1)"); -} -if (!FetchOneColumn()) { - Verbose("Couldn't get the lock to do the shadow database syncing."); - exit; -} - -my $shadowtable = "$::db_name.shadowlog"; - -if (!$syncall) { - Verbose("Looking for requests to sync the whole database."); - SendSQL("SELECT id FROM $shadowtable " . - "WHERE reflected = 0 AND command = 'SYNCUP'"); - if (FetchOneColumn()) { - $syncall = 1; - } -} - -if ($syncall) { - Verbose("Syncing up the shadow database by copying entire database in."); - if ($wasusing) { - SetParam('queryagainstshadowdb',0); - WriteParams(); - if (! $shutdown) { - Verbose("Disabled reading from the shadowdb. Sleeping 10 seconds to let other procs catch up."); - sleep(10); - } - SetParam('queryagainstshadowdb', 1); - } - my @tables; - SendSQL("SHOW TABLES"); - my $query = ""; - while (MoreSQLData()) { - my $table = FetchOneColumn(); - push(@tables, $table); - if ($query) { - $query .= ", $table WRITE"; - } else { - $query = "LOCK TABLES $table WRITE"; - } - } - if (@tables) { - Verbose("Locking entire shadow database"); - SendSQL($query); - foreach my $table (@tables) { - Verbose("Dropping old shadow table $table"); - SendSQL("DROP TABLE $table"); - } - SendSQL("UNLOCK TABLES"); - } - # Carefully lock the whole real database for reading, except for the - # shadowlog table, which we lock for writing. Then dump everything - # into the shadowdb database. Then mark everything in the shadowlog - # as reflected. Only then unlock everything. This sequence causes - # us to be sure not to miss anything or get something twice. - SendSQL("USE $::db_name"); - SendSQL("SHOW TABLES"); - @tables = (); - $query = "LOCK TABLES shadowlog WRITE"; - while (MoreSQLData()) { - my $table = FetchOneColumn(); - if ($table ne "shadowlog") { - $query .= ", $table READ"; - push(@tables, $table); - } - } - Verbose("Locking entire database"); - SendSQL($query); - 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" } - if ($::db_sock) { push @ARGS, "-S$::db_sock" } - push @ARGS, "-l", "-e", $::db_name, @tables; - open SAVEOUT, ">&STDOUT"; # stash the original output stream - open STDOUT, ">$tempfile"; # redirect to file - select STDOUT; $| = 1; # disable buffering - system("$::mysqlpath/mysqldump", @ARGS); - open STDOUT, ">&SAVEOUT"; # redirect back to original stream - Verbose("Restoring from tempfile into shadowdb"); - my $extra = "-u $::db_user"; - if ($::db_pass) { - $extra .= " -p$::db_pass"; - } - if ($::db_sock) { - $extra .= " -S$::db_sock"; - } - if ($verbose) { - $extra .= " -v"; - } - open(MYSQL, "/bin/cat $tempfile | $::mysqlpath/mysql $extra " . - Param("shadowdb") . "|") || die "Couldn't do db copy"; - my $count = 0; - while (<MYSQL>) { - print "."; - $count++; - if ($count % 70 == 0) { - print "\n"; - } - } - close(MYSQL); - unlink($tempfile); - Verbose(""); - - - $::dbwritesallowed = 1; -# SendSQL("UPDATE shadowlog SET reflected = 1 WHERE reflected = 0", 1); - SendSQL("DELETE FROM shadowlog", 1); - SendSQL("UNLOCK TABLES"); - if ($wasusing) { - Verbose("Reenabling other processes to read from the shadow db"); - SetParam('queryagainstshadowdb', 1); - WriteParams(); - } - if ($shutdown) { - Verbose("Restoring the original shutdown message (if any)"); - SetParam('shutdownhtml', $wasshutdown); - WriteParams(); - } - Verbose("OK, done."); -} - -Verbose("Looking for commands to execute."); -$::dbwritesallowed = 1; - -# Make us low priority, to not block anyone who is trying to actually use -# the shadowdb. Note that this is carefully coded to ignore errors; we want -# to keep going even on older mysqld's that don't have the -# SQL_LOW_PRIORITY_UPDATES option. -$::db->do("SET OPTION SQL_LOW_PRIORITY_UPDATES = 1"); - -while (1) { - SendSQL("SELECT id, command FROM $shadowtable WHERE reflected = 0 " . - "ORDER BY id LIMIT 1"); - my ($id, $command) = (FetchSQLData()); - if (!$id) { - last; - } - Verbose("Executing command in shadow db: $command"); - SendSQL($command, 1); - SendSQL("UPDATE $shadowtable SET reflected = 1 WHERE id = $id", 1); -} - -Verbose("Releasing lock."); -SendSQL("SELECT RELEASE_LOCK('synclock')"); |