diff options
author | bbaetz%student.usyd.edu.au <> | 2002-12-21 08:35:14 +0100 |
---|---|---|
committer | bbaetz%student.usyd.edu.au <> | 2002-12-21 08:35:14 +0100 |
commit | a4e7f360c91236168a903e74ab3669a3f03bc690 (patch) | |
tree | 4d4c988aff412809ea1a0e0ce5c12380e0906e11 | |
parent | a40d927bfd9a9b3012be9e0f85da84aa4dd58344 (diff) | |
download | bugzilla-a4e7f360c91236168a903e74ab3669a3f03bc690.tar.gz bugzilla-a4e7f360c91236168a903e74ab3669a3f03bc690.tar.xz |
Bug 180870 - Remove old shadowdb manual replication code
r, a=myk
-rwxr-xr-x | checksetup.pl | 16 | ||||
-rw-r--r-- | defparams.pl | 79 | ||||
-rw-r--r-- | docs/sgml/administration.sgml | 31 | ||||
-rw-r--r-- | docs/sgml/database.sgml | 5 | ||||
-rw-r--r-- | docs/sgml/installation.sgml | 4 | ||||
-rw-r--r-- | docs/xml/administration.xml | 31 | ||||
-rw-r--r-- | docs/xml/database.xml | 5 | ||||
-rw-r--r-- | docs/xml/installation.xml | 4 | ||||
-rwxr-xr-x | doeditparams.cgi | 5 | ||||
-rw-r--r-- | globals.pl | 79 | ||||
-rwxr-xr-x | post_bug.cgi | 10 | ||||
-rwxr-xr-x | syncshadowdb | 327 | ||||
-rw-r--r-- | template/en/default/global/footer.html.tmpl | 2 |
13 files changed, 55 insertions, 543 deletions
diff --git a/checksetup.pl b/checksetup.pl index fbe0c0051..18b45dda5 100755 --- a/checksetup.pl +++ b/checksetup.pl @@ -820,7 +820,7 @@ if ($my_create_htaccess) { open HTACCESS, ">.htaccess"; print HTACCESS <<'END'; # don't allow people to retrieve non-cgi executable files or our private data -<FilesMatch ^(.*\.pl|localconfig|processmail|syncshadowdb|runtests.sh)$> +<FilesMatch ^(.*\.pl|localconfig|processmail|runtests.sh)$> deny from all </FilesMatch> END @@ -1085,7 +1085,7 @@ WriteParams(); # These are the files which need to be marked executable my @executable_files = ('processmail', 'whineatnews.pl', 'collectstats.pl', - 'checksetup.pl', 'syncshadowdb', 'importxml.pl', 'runtests.sh'); + 'checksetup.pl', 'importxml.pl', 'runtests.sh'); # tell me if a file is executable. All CGI files and those in @executable_files # are executable @@ -1648,13 +1648,6 @@ $table{milestones} = sortkey smallint not null, unique (product_id, value)'; -$table{shadowlog} = - 'id int not null auto_increment primary key, - ts timestamp, - reflected tinyint not null, - command mediumtext not null, - index(reflected)'; - # GRM $table{duplicates} = 'dupe_of mediumint(9) not null, @@ -3828,6 +3821,11 @@ if ($sth->rows == 0) { } } +# 2002-11-XX Bug 180870 - remove manual shadowdb replication code +if (TableExists('shadowlog')) { + print "Removing shadowlog table\n"; + $dbh->do("DROP TABLE shadowlog"); +} # # Final checks... diff --git a/defparams.pl b/defparams.pl index f5ae590cc..1d6712a6a 100644 --- a/defparams.pl +++ b/defparams.pl @@ -67,30 +67,14 @@ sub check_shadowdb { if ($value eq "") { return ""; } - if (!Param("updateshadowdb")) { - # Can't test this, because ConnectToDatabase uses the param, but - # we can't set this before testing.... - return ""; - } - &::SendSQL("SHOW DATABASES"); - while (&::MoreSQLData()) { - my $n = &::FetchOneColumn(); - if (lc($n) eq lc($value)) { - return "The $n database already exists. If that's really the name you want to use for the backup, please CAREFULLY make the existing database go away somehow, and then try again."; - } - } - # We trust the admin.... - trick_taint($value); - &::SendSQL("CREATE DATABASE $value"); - &::SendSQL("INSERT INTO shadowlog (command) VALUES ('SYNCUP')", 1); - return ""; -} -sub check_shadowdbhost { - my ($value) = (@_); - if ($value && Param("updateshadowdb")) { - return "Sorry, you can't have the shadowdb on a different connection to the main database if you want Bugzilla to handle the replication for you."; + if (!Param('shadowdbhost')) { + return "You need to specify a host when using a shadow database"; } + + # Can't test existance of this because ConnectToDatabase uses the param, + # but we can't set this before testing.... + # This can really only be fixed after we can use the DBI more openly return ""; } @@ -271,50 +255,10 @@ sub check_netmask { }, { - name => 'queryagainstshadowdb', - desc => 'If this is on, and the <tt>shadowdb</tt> parameter is set, then ' . - 'certain queries will happen against the shadow database.', - type => 'b', - default => 0, - }, - - { - name => 'updateshadowdb', - desc => 'If this is on, and the <tt>shadowdb</tt> parameter is set, then ' . - 'Bugzilla will use the old style of shadow database in which it ' . - 'manually propogates changes to the shadow database. Otherwise, ' . - 'Bugzilla will assume that the <tt>shadowdb</tt> database (if ' . - 'any) is being updated via replication. <b>WARNING! This ' . - 'manual replication is deprecated and is going away soon ' . - '(<u>BEFORE</u> the next stable Bugzilla release).</b> It has ' . - 'several problems with data consistency, and replication is the ' . - 'preferred option. If this parameter is on, and you disable it, ' . - 'make sure that the shadow database is already set up for ' . - 'replication, or queries will return stale data.', - type => 'b', - default => 1, - }, - - # This entry must be _after_ updateshadowdb, because check_shadowdbhost uses - # that - { name => 'shadowdbhost', - desc => 'The host the shadow database is on. If blank, then then we ' . - 'assume it\'s on the main database host (as defined in ' . - 'localconfig) and ingore the <tt>shadowdbport</tt> and ' . - '<tt>shadowdbsock</tt> parameters below, which means that this ' . - 'parameter <em>must be filled in</em> if your shadow database is ' . - 'on a different instance of the mysql server, even if that ' . - 'instance runs on the same machine as the main database. Note ' . - 'that <tt>updateshadowdb</tt> must be off if the shadow database ' . - 'is on a difference mysql instance, since Bugzilla can\'t ' . - 'propogate changes between instances itself, and this should be ' . - 'left blank if the shadow database is on the same instance, ' . - 'since Bugzilla can then reuse the same database connection for '. - 'better performance.', + desc => 'The host the shadow database is on.', type => 't', default => '', - checker => \&check_shadowdbhost, }, { @@ -346,11 +290,12 @@ sub check_netmask { { name => 'shadowdb', desc => 'If non-empty, then this is the name of another database in ' . - 'which Bugzilla will keep a shadow read-only copy of everything. ' . + 'which Bugzilla will use as a read-only copy of everything. ' . 'This is done so that long slow read-only operations can be used ' . - 'against this db, and not lock up things for everyone else. ' . - 'Turning on this parameter will create the given database ; be ' . - 'careful not to use the name of an existing database with useful ' . 'data in it!', + 'against this db, and not lock up things for everyone else. This ' . + 'database is on the <tt>shadowdbhost</tt>, and must exist. ' . + 'Bugzilla does not update it, if you use this paramater, then ' . + 'you need to set up replication for your database', type => 't', default => '', checker => \&check_shadowdb diff --git a/docs/sgml/administration.sgml b/docs/sgml/administration.sgml index 1873ee025..847527203 100644 --- a/docs/sgml/administration.sgml +++ b/docs/sgml/administration.sgml @@ -69,8 +69,14 @@ write locking. What this means is that if someone needs to make a change to a bug, they will lock the entire table until the operation is complete. Locking for write also blocks reads until the write is - complete. The - <quote>shadowdb</quote> + complete. Note that more recent versions of mysql support row level + locking using different table types. These types are slower than the + standard type, and Bugzilla does not yet take advantage of features + such as transactions which would justify this speed decrease. The + Bugzilla team are, however, happy to hear about any experiences with + row level locking and Bugzilla</para> + + <para>The <quote>shadowdb</quote> parameter was designed to get around this limitation. While only a single user is allowed to write to a table at a time, reads can continue unimpeded on a read-only shadow copy of the database. @@ -85,23 +91,10 @@ Bugzilla bug changes and comments per day.</para> <para>The value of the parameter defines the name of the - shadow bug database. - Set "shadowdb" to e.g. "bug_shadowdb" if you will be running a - *very* large installation of Bugzilla. - <note> - <para>Enabling "shadowdb" can adversely affect the stability of - your installation of Bugzilla. You should regularly check that your - database is in sync. It is often advisable to force a shadow - database sync nightly via - <quote>cron</quote>. - </para> - </note> - </para> - - <para>If you use the "shadowdb" option, it is only natural that you - should turn the "queryagainstshadowdb" option on as well. Otherwise - you are replicating data into a shadow database for no reason!</para> - + shadow bug database. You will need to set the host and port settings + from the params page, and set up replication in your database server + so that updates reach this readonly mirror. Consult your database + documentation for more detail.</para> </step> <step> diff --git a/docs/sgml/database.sgml b/docs/sgml/database.sgml index ae1918207..d32bb57cc 100644 --- a/docs/sgml/database.sgml +++ b/docs/sgml/database.sgml @@ -198,7 +198,6 @@ | products | | profiles | | profiles_activity | -| shadowlog | | tokens | | versions | | votes | @@ -290,10 +289,6 @@ sshh... don't tell your users!) profiles_activity: Need to know who did what when to who's profile? This'll tell you, it's a pretty complete history. -shadowlog: I could be mistaken here, but I believe this table tells you when -your shadow database is updated and what commands were used to update it. We -don't use a shadow database at our site yet, so it's pretty empty for us. - versions: Version information for every product votes: Who voted for what when diff --git a/docs/sgml/installation.sgml b/docs/sgml/installation.sgml index 8d1a94ec7..7aec021ce 100644 --- a/docs/sgml/installation.sgml +++ b/docs/sgml/installation.sgml @@ -559,9 +559,7 @@ AllowOverride Limit <para>There are important files and directories that should not be a served by the HTTP server - most files in the <quote>data</quote> - and - <quote>shadow</quote> - directories and the + directory and the <quote>localconfig</quote> file. You should configure your HTTP server to not serve these files. Failure to do so will expose critical passwords and diff --git a/docs/xml/administration.xml b/docs/xml/administration.xml index 1873ee025..847527203 100644 --- a/docs/xml/administration.xml +++ b/docs/xml/administration.xml @@ -69,8 +69,14 @@ write locking. What this means is that if someone needs to make a change to a bug, they will lock the entire table until the operation is complete. Locking for write also blocks reads until the write is - complete. The - <quote>shadowdb</quote> + complete. Note that more recent versions of mysql support row level + locking using different table types. These types are slower than the + standard type, and Bugzilla does not yet take advantage of features + such as transactions which would justify this speed decrease. The + Bugzilla team are, however, happy to hear about any experiences with + row level locking and Bugzilla</para> + + <para>The <quote>shadowdb</quote> parameter was designed to get around this limitation. While only a single user is allowed to write to a table at a time, reads can continue unimpeded on a read-only shadow copy of the database. @@ -85,23 +91,10 @@ Bugzilla bug changes and comments per day.</para> <para>The value of the parameter defines the name of the - shadow bug database. - Set "shadowdb" to e.g. "bug_shadowdb" if you will be running a - *very* large installation of Bugzilla. - <note> - <para>Enabling "shadowdb" can adversely affect the stability of - your installation of Bugzilla. You should regularly check that your - database is in sync. It is often advisable to force a shadow - database sync nightly via - <quote>cron</quote>. - </para> - </note> - </para> - - <para>If you use the "shadowdb" option, it is only natural that you - should turn the "queryagainstshadowdb" option on as well. Otherwise - you are replicating data into a shadow database for no reason!</para> - + shadow bug database. You will need to set the host and port settings + from the params page, and set up replication in your database server + so that updates reach this readonly mirror. Consult your database + documentation for more detail.</para> </step> <step> diff --git a/docs/xml/database.xml b/docs/xml/database.xml index ae1918207..d32bb57cc 100644 --- a/docs/xml/database.xml +++ b/docs/xml/database.xml @@ -198,7 +198,6 @@ | products | | profiles | | profiles_activity | -| shadowlog | | tokens | | versions | | votes | @@ -290,10 +289,6 @@ sshh... don't tell your users!) profiles_activity: Need to know who did what when to who's profile? This'll tell you, it's a pretty complete history. -shadowlog: I could be mistaken here, but I believe this table tells you when -your shadow database is updated and what commands were used to update it. We -don't use a shadow database at our site yet, so it's pretty empty for us. - versions: Version information for every product votes: Who voted for what when diff --git a/docs/xml/installation.xml b/docs/xml/installation.xml index 8d1a94ec7..7aec021ce 100644 --- a/docs/xml/installation.xml +++ b/docs/xml/installation.xml @@ -559,9 +559,7 @@ AllowOverride Limit <para>There are important files and directories that should not be a served by the HTTP server - most files in the <quote>data</quote> - and - <quote>shadow</quote> - directories and the + directory and the <quote>localconfig</quote> file. You should configure your HTTP server to not serve these files. Failure to do so will expose critical passwords and diff --git a/doeditparams.cgi b/doeditparams.cgi index 4dd4f8b52..d37e8b207 100755 --- a/doeditparams.cgi +++ b/doeditparams.cgi @@ -101,11 +101,6 @@ foreach my $i (GetParamList()) { WriteParams(); unlink "data/versioncache"; -if (Param("updateshadowdb")) { - print "<PRE>"; - system("./syncshadowdb", "-v"); - print "</PRE>"; -} print "OK, done.<p>\n"; print "<a href=editparams.cgi>Edit the params some more.</a><p>\n"; diff --git a/globals.pl b/globals.pl index a2dbcaff8..28e065f98 100644 --- a/globals.pl +++ b/globals.pl @@ -109,19 +109,16 @@ $::dbwritesallowed = 1; sub ConnectToDatabase { my ($useshadow) = (@_); $::dbwritesallowed = !$useshadow; - $useshadow = ($useshadow && Param("shadowdb") && - Param("queryagainstshadowdb")); - my $useshadow_dbh = ($useshadow && Param("shadowdbhost") ne ""); - my $name = $useshadow ? Param("shadowdb") : $::db_name; + $useshadow &&= Param("shadowdb"); my $connectstring; - if ($useshadow_dbh) { + if ($useshadow) { if (defined $::shadow_dbh) { $::db = $::shadow_dbh; return; } $connectstring="DBI:mysql:host=" . Param("shadowdbhost") . - ";database=$name;port=" . Param("shadowdbport"); + ";database=" . Param('shadowdb') . ";port=" . Param("shadowdbport"); if (Param("shadowdbsock") ne "") { $connectstring .= ";mysql_socket=" . Param("shadowdbsock"); } @@ -130,7 +127,7 @@ sub ConnectToDatabase { $::db = $::main_dbh; return; } - $connectstring="DBI:mysql:host=$::db_host;database=$name;port=$::db_port"; + $connectstring="DBI:mysql:host=$::db_host;database=$::db_name;port=$::db_port"; if ($::db_sock ne "") { $connectstring .= ";mysql_socket=$::db_sock"; } @@ -141,7 +138,7 @@ sub ConnectToDatabase { Param("maintainer") . ". The error you should quote is: " . $DBI::errstr; - if ($useshadow_dbh) { + if ($useshadow) { $::shadow_dbh = $::db; } else { $::main_dbh = $::db; @@ -149,58 +146,17 @@ sub ConnectToDatabase { } sub ReconnectToShadowDatabase { - # This will connect us to the shadowdb if we're not already connected, - # but if we're using the same dbh for both the main db and the shadowdb, - # be sure to USE the correct db - if (Param("shadowdb") && Param("queryagainstshadowdb")) { + if (Param("shadowdb")) { ConnectToDatabase(1); - if (!Param("shadowdbhost")) { - SendSQL("USE " . Param("shadowdb")); - } } } sub ReconnectToMainDatabase { - if (Param("shadowdb") && Param("queryagainstshadowdb")) { + if (Param("shadowdb")) { ConnectToDatabase(); - if (!Param("shadowdbhost")) { - SendSQL("USE $::db_name"); - } - } -} - -my $shadowchanges = 0; -sub SyncAnyPendingShadowChanges { - if ($shadowchanges && Param("updateshadowdb")) { - my $pid; - FORK: { - if ($pid = fork) { # create a fork - # parent code runs here - $shadowchanges = 0; - return; - } elsif (defined $pid) { - # child process code runs here - my $redir = ($^O =~ /MSWin32/i) ? "NUL" : "/dev/null"; - open STDOUT,">$redir"; - open STDERR,">$redir"; - exec("./syncshadowdb","--") or die "Unable to exec syncshadowdb: $!"; - # the idea was that passing the second parameter tricks it into - # using execvp instead of running a shell. Not really necessary since - # there are no shell meta-characters, but it passes our tinderbox - # test that way. :) http://bugzilla.mozilla.org/show_bug.cgi?id=21253 - } elsif ($! =~ /No more process/) { - # recoverable fork error, try again in 5 seconds - sleep 5; - redo FORK; - } else { - # something weird went wrong - die "Can't create background process to run syncshadowdb: $!"; - } - } } } - # This is used to manipulate global state used by SendSQL(), # MoreSQLData() and FetchSQLData(). It provides a way to do another # SQL query without losing any as-yet-unfetched data from an existing @@ -248,7 +204,7 @@ sub SqlLog { } sub SendSQL { - my ($str, $dontshadow) = (@_); + my ($str) = (@_); # Don't use DBI's taint stuff yet, because: # a) We don't want out vars to be tainted (yet) @@ -262,12 +218,10 @@ sub SendSQL { if ($iswrite && !$::dbwritesallowed) { die "Evil code attempted to write '$str' to the shadow database"; } - if ($str =~ /^LOCK TABLES/i && $str !~ /shadowlog/ && $::dbwritesallowed) { - $str =~ s/^LOCK TABLES/LOCK TABLES shadowlog WRITE, /i; - } + # If we are shutdown, we don't want to run queries except in special cases if (Param('shutdownhtml')) { - if ($0 =~ m:[\\/]((do)?editparams.cgi|syncshadowdb)$:) { + if ($0 =~ m:[\\/]((do)?editparams.cgi)$:) { $::ignorequery = 0; } else { $::ignorequery = 1; @@ -284,19 +238,6 @@ sub SendSQL { die "$str: " . $errstr; } SqlLog("Done"); - if (!$dontshadow && $iswrite && Param("shadowdb") && Param("updateshadowdb")) { - my $q = SqlQuote($str); - my $insertid; - if ($str =~ /^(INSERT|REPLACE)/i) { - SendSQL("SELECT LAST_INSERT_ID()"); - $insertid = FetchOneColumn(); - } - SendSQL("INSERT INTO shadowlog (command) VALUES ($q)", 1); - if ($insertid) { - SendSQL("SET LAST_INSERT_ID = $insertid"); - } - $shadowchanges++; - } } sub MoreSQLData { diff --git a/post_bug.cgi b/post_bug.cgi index 2a65c2436..18b761744 100755 --- a/post_bug.cgi +++ b/post_bug.cgi @@ -395,14 +395,6 @@ while (MoreSQLData()) { push(@groupstoadd, $id) } } - - -# Lock tables before inserting records for the new bug into the database -# if we are using a shadow database to prevent shadow database corruption -# when two bugs get created at the same time. -SendSQL("LOCK TABLES bugs WRITE, bug_group_map WRITE, longdescs WRITE, " . - "cc WRITE, keywords WRITE, dependencies WRITE, bugs_activity WRITE, " . - "fielddefs READ, profiles READ, keyworddefs READ") if Param("shadowdb"); # Add the bug report to the DB. SendSQL($sql); @@ -465,8 +457,6 @@ if (UserInGroup("editbugs")) { } } -SendSQL("UNLOCK TABLES") if Param("shadowdb"); - # Assemble the -force* strings so this counts as "Added to this capacity" my @ARGLIST = (); if (@cc) { 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')"); diff --git a/template/en/default/global/footer.html.tmpl b/template/en/default/global/footer.html.tmpl index 7baf3207a..6e7aec377 100644 --- a/template/en/default/global/footer.html.tmpl +++ b/template/en/default/global/footer.html.tmpl @@ -53,5 +53,3 @@ </body> </html> - -[% CALL SyncAnyPendingShadowChanges() IF SyncAnyPendingShadowChanges %] |