2000-02-18 00:41:39 +03:00
|
|
|
#!/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 diagnostics;
|
|
|
|
use strict;
|
|
|
|
|
|
|
|
require "globals.pl";
|
2000-03-20 21:48:59 +03:00
|
|
|
require "defparams.pl";
|
2000-02-18 00:41:39 +03:00
|
|
|
|
|
|
|
# Shut up misguided -w warnings about "used only once". "use vars" just
|
|
|
|
# doesn't work for me.
|
|
|
|
|
|
|
|
sub sillyness {
|
|
|
|
my $zz;
|
|
|
|
$zz = $::dbwritesallowed;
|
|
|
|
}
|
|
|
|
|
|
|
|
my $verbose = 0;
|
2000-03-20 21:48:59 +03:00
|
|
|
my $syncall = 0;
|
|
|
|
|
|
|
|
sub Usage {
|
|
|
|
print "Usage: syncshadowdb [-v] [-syncall]\n";
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach my $opt (@ARGV) {
|
|
|
|
if ($opt eq '-v') {
|
|
|
|
$verbose = 1;
|
|
|
|
} elsif ($opt eq '-syncall') {
|
|
|
|
$syncall = 1;
|
|
|
|
$verbose = 1;
|
|
|
|
} else {
|
|
|
|
Usage();
|
|
|
|
}
|
2000-02-18 00:41:39 +03:00
|
|
|
}
|
|
|
|
$| = 1;
|
|
|
|
|
2000-03-20 21:48:59 +03:00
|
|
|
my $logtostderr = 0;
|
|
|
|
|
2000-02-18 00:41:39 +03:00
|
|
|
sub Verbose ($) {
|
|
|
|
my ($str) = (@_);
|
|
|
|
if ($verbose) {
|
2000-03-20 21:48:59 +03:00
|
|
|
if ($logtostderr) {
|
|
|
|
print STDERR $str, "\n";
|
|
|
|
} else {
|
|
|
|
print $str, "\n";
|
|
|
|
}
|
2000-02-18 00:41:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
my $db_name = "bugs";
|
|
|
|
require "localconfig";
|
|
|
|
|
|
|
|
if (!Param("shadowdb")) {
|
|
|
|
Verbose("We don't have shadow databases turned on; no syncing performed.");
|
|
|
|
exit;
|
|
|
|
}
|
|
|
|
|
2000-03-20 21:48:59 +03:00
|
|
|
my $wasusing = Param("queryagainstshadowdb");
|
|
|
|
|
|
|
|
$::param{'queryagainstshadowdb'} = 1; # Force us to be able to use the
|
|
|
|
# shadowdb, even if other processes
|
|
|
|
# are not supposed to.
|
|
|
|
|
|
|
|
|
2000-02-18 00:41:39 +03:00
|
|
|
ConnectToDatabase(1);
|
|
|
|
|
2000-03-20 21:48:59 +03:00
|
|
|
Verbose("Aquiring lock.");
|
2000-02-18 00:41:39 +03:00
|
|
|
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";
|
|
|
|
|
2000-03-20 21:48:59 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2000-02-18 00:41:39 +03:00
|
|
|
|
2000-03-20 21:48:59 +03:00
|
|
|
if ($syncall) {
|
2000-02-18 00:41:39 +03:00
|
|
|
Verbose("Syncing up the shadow database by copying entire database in.");
|
2000-03-20 21:48:59 +03:00
|
|
|
if ($wasusing) {
|
|
|
|
$::param{'queryagainstshadowdb'} = 0;
|
|
|
|
WriteParams();
|
|
|
|
Verbose("Disabled reading from the shadowdb. Sleeping 10 seconds to let other procs catch up.");
|
|
|
|
sleep(10);
|
|
|
|
$::param{'queryagainstshadowdb'} = 1;
|
|
|
|
}
|
2000-02-18 00:41:39 +03:00
|
|
|
my @tables;
|
|
|
|
SendSQL("SHOW TABLES");
|
2000-03-20 21:48:59 +03:00
|
|
|
my $query = "";
|
2000-02-18 00:41:39 +03:00
|
|
|
while (MoreSQLData()) {
|
|
|
|
my $table = FetchOneColumn();
|
|
|
|
push(@tables, $table);
|
2000-03-20 21:48:59 +03:00
|
|
|
if ($query) {
|
|
|
|
$query .= ", $table WRITE";
|
|
|
|
} else {
|
|
|
|
$query = "LOCK TABLES $table WRITE";
|
|
|
|
}
|
2000-02-18 00:41:39 +03:00
|
|
|
}
|
2000-03-20 21:48:59 +03:00
|
|
|
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");
|
|
|
|
}
|
2000-02-18 00:41:39 +03:00
|
|
|
# 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 = ();
|
2000-03-20 21:48:59 +03:00
|
|
|
$query = "LOCK TABLES shadowlog WRITE";
|
2000-02-18 00:41:39 +03:00
|
|
|
while (MoreSQLData()) {
|
|
|
|
my $table = FetchOneColumn();
|
|
|
|
if ($table ne "shadowlog") {
|
|
|
|
$query .= ", $table READ";
|
|
|
|
push(@tables, $table);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Verbose("Locking entire database");
|
|
|
|
SendSQL($query);
|
|
|
|
my $tablelist = join(' ', @tables);
|
2000-03-20 21:48:59 +03:00
|
|
|
my $tempfile = "data/tmpsyncshadow.$$";
|
|
|
|
Verbose("Dumping database to a temp file ($tempfile).");
|
|
|
|
system("mysqldump -l -e $db_name $tablelist > $tempfile");
|
|
|
|
Verbose("Restoring from tempfile into shadowdb");
|
2000-02-18 00:41:39 +03:00
|
|
|
my $extra = "";
|
|
|
|
if ($verbose) {
|
|
|
|
$extra = "-v";
|
|
|
|
}
|
2000-03-20 21:48:59 +03:00
|
|
|
open(MYSQL, "cat $tempfile | mysql $extra " .
|
2000-02-18 00:41:39 +03:00
|
|
|
Param("shadowdb") . "|") || die "Couldn't do db copy";
|
|
|
|
my $count = 0;
|
|
|
|
while (<MYSQL>) {
|
|
|
|
print ".";
|
|
|
|
$count++;
|
|
|
|
if ($count % 70 == 0) {
|
|
|
|
print "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close(MYSQL);
|
2000-03-20 21:48:59 +03:00
|
|
|
unlink($tempfile);
|
2000-02-18 00:41:39 +03:00
|
|
|
Verbose("");
|
|
|
|
|
|
|
|
|
2000-03-20 21:48:59 +03:00
|
|
|
$::dbwritesallowed = 1;
|
2000-02-18 00:41:39 +03:00
|
|
|
SendSQL("UPDATE shadowlog SET reflected = 1 WHERE reflected = 0", 1);
|
|
|
|
SendSQL("UNLOCK TABLES");
|
2000-03-20 21:48:59 +03:00
|
|
|
if ($wasusing) {
|
|
|
|
Verbose("Reenabling other processes to read from the shadow db");
|
|
|
|
$::param{'queryagainstshadowdb'} = 1;
|
|
|
|
WriteParams();
|
|
|
|
}
|
2000-02-18 00:41:39 +03:00
|
|
|
Verbose("OK, done.");
|
|
|
|
}
|
|
|
|
|
2000-03-20 21:48:59 +03:00
|
|
|
Verbose("Looking for commands to execute.");
|
|
|
|
$::dbwritesallowed = 1;
|
2000-02-18 00:41:39 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2000-03-20 21:48:59 +03:00
|
|
|
Verbose("Releasing lock.");
|
2000-02-18 00:41:39 +03:00
|
|
|
SendSQL("SELECT RELEASE_LOCK('synclock')");
|