blob: 56710d498d17038574f85b87be2fb944383ec387 [file]
#!/usr/bin/perl
#
# @@@ START COPYRIGHT @@@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
# @@@ END COPYRIGHT @@@
#
use strict;
my %volume_info = (); # Store all the results
my $volcheck; # Volume to check
my $cluster; # Are we on a cluster?
my $pdshres; # Keep track of $SQ_PDSH output
my $g_dotse = 1; # Do we think mirroring is on for TSE
my $g_doase = 1; # Do we think mirroring is on for ASE
#
# Display the contents of the volume_info hash
#
sub print_results()
{
print "\nRESULTS:\n\n" if (!$cluster);
for my $k1 (sort(keys(%volume_info)))
{
print "$k1\n";
print "-------\n";
print "PRIM files: $volume_info{$k1}{'prim'}{numfiles}\n";
print "PRIM diff errs: $volume_info{$k1}{'prim'}{err}\n";
print "PRIM problem files: $volume_info{$k1}{'prim'}{problemfiles}\n";
print "MIR files: $volume_info{$k1}{'mir'}{numfiles}\n";
print "MIR diff errs: $volume_info{$k1}{'mir'}{err}\n";
print "MIR problem files: $volume_info{$k1}{'mir'}{problemfiles}\n\n";
}
}
#
# Process the contents of either the sq_tse.create or sq_ase.create
#
sub process_vol($)
{
my $tsevols = shift(@_);
my @problemfiles = ();
my $i = 0;
my $errs = 0;
my $numfiles = 0;
my @tseitems;
my @tsedirp;
my @tsedirm;
my $tsedirps;
my $tsedirms;
my $tseprimfiles;
my $tsemirfiles;
my $cmd;
my $vol;
my @volfields;
my $tsefile;
my $blink = 0; # Just for fun
my @items = split(/\n/, $tsevols);
foreach (@items)
{
if (($i % 2) != 0) { $i++; next; }
# Logic of this block may have to change if, in the future,
# the order of the volumes in the sq_*se.create scripts changes
@tsedirp = split(/\s+/, $items[$i]);
$tsedirps = $tsedirp[-1];
$tsedirps = $tsedirps . "/";
@tsedirm = split(/\s+/, $items[$i+1]);
$tsedirms = $tsedirm[-1];
@volfields = split(/\//, $tsedirms);
$tsedirms = $tsedirms . "/";
$tseprimfiles = `ls $tsedirps`;
$tsemirfiles = `ls $tsedirms`;
chomp($tseprimfiles);
chomp($tsemirfiles);
$vol = $volfields[-1];
substr($vol, 0, 1) = "";
print "Diffing $vol files: " if (!$cluster);
# Diff PRIM to MIR
for $tsefile (split(/\n/, $tseprimfiles))
{
next if ($tsefile =~ /lost\+found/);
print $tsefile if (!$cluster);
$cmd = "diff $tsedirps" . "$tsefile " . "$tsedirms" . "$tsefile 2> /dev/null";
`$cmd`;
if (!$cluster)
{
while ($blink < length($tsefile))
{
print "\b";
$blink++;
}
}
if ($? != 0)
{
push(@problemfiles, $tsefile);
$errs++;
}
$numfiles++;
$blink = 0;
}
$volume_info{$vol}{'prim'}{err} = $errs;
$volume_info{$vol}{'prim'}{numfiles} = $numfiles;
$volume_info{$vol}{'prim'}{problemfiles} = join("\n\t\t ", @problemfiles);
$errs = 0;
$numfiles = 0;
@problemfiles = ();
# Diff MIR files to PRIM files, to catch any extra files in the MIR directory
for $tsefile (split(/\n/, $tsemirfiles))
{
next if ($tsefile =~ /lost\+found/);
print $tsefile if (!$cluster);
$cmd = "diff $tsedirps" . "$tsefile " . "$tsedirms" . "$tsefile 2> /dev/null";
`$cmd`;
if (!$cluster)
{
while ($blink < length($tsefile))
{
print "\b";
$blink++;
}
}
if ($? != 0)
{
push(@problemfiles, $tsefile);
$errs++;
}
$numfiles++;
$blink = 0;
}
$volume_info{$vol}{'mir'}{err} = $errs;
$volume_info{$vol}{'mir'}{numfiles} = $numfiles;
$volume_info{$vol}{'mir'}{problemfiles} = join("\n\t\t ", @problemfiles);
print "\n";
$errs = 0;
$numfiles = 0;
$i++;
@problemfiles = ();
}
}
#
# On a cluster, use $SQ_PDSH to call the correct storage nodes for
# each SE volume.
#
sub do_pdsh($)
{
my $sevols = shift(@_);
my ($vol, @pdshcmd, @fields, $cmd);
foreach $vol (split(/\n/, $sevols))
{
next if ($vol =~ /databasem/);
@pdshcmd = split(/\s+/, $vol);
@fields = split(/\//, $vol);
print "Diffing " . substr($fields[-1], 1) . " (on $pdshcmd[2])...";
$cmd = $ENV{'SQ_PDSH'} . " -w $pdshcmd[2] \'dbcheck $fields[-1] --cluster\'";
$pdshres .= `$cmd`;
chop($pdshres);
print "done\n";
}
}
#
# Show usage information.
#
sub show_help()
{
print <<END
Usage: dbcheck [--help] <volname>
Diff files between the primary and mirror volumes, to verify consistency.
Note that on a cluster, dbcheck will utilize pdsh to call the correct
storage nodes for the volumes.
Options:
--help Display this usage information.
<volname> Optional, can be used to specify a specific SE volume
to check. If <volname> isn't specified, all volumes
are checked. The leading '$' is optional, and it is
case-insensitive.
END
}
#
# This utility is only useful if user has mirroring turned on
#
sub mirroring_not_on()
{
my $cmd;
$cmd = "grep DEVICE-M $ENV{'TRAF_HOME'}/sql/scripts/gomon.cold | egrep \"DATA|SYSTEM\"";
`$cmd`;
$g_dotse = 0 if ($? != 0);
$cmd = "grep DEVICE-M $ENV{'TRAF_HOME'}/sql/scripts/gomon.cold | egrep \"AUDIT|TLOG\"";
`$cmd`;
$g_doase = 0 if ($? != 0);
if ($g_dotse == 1 || $g_doase == 1) { return 0; }
else { return 1; }
}
#
# Call process_vol with the list of necessary TSE/ASE volumes to diff
#
sub main()
{
my ($asevols, $tsevols, $cmd);
print STDERR "You should not be trying to use the script, it is broken\n";
exit;
if (mirroring_not_on())
{
print "Error: databasem directory not detected in TSE/ASE creation scripts.\nIs mirroring enabled?\n";
exit 1;
}
if ($#ARGV >= 0)
{
if ($ARGV[0] =~ /help/ || $ARGV[0] eq "-h")
{
show_help();
exit (0);
}
$volcheck = $ARGV[0];
$volcheck = uc($volcheck);
$cluster = 1 if ($ARGV[1] eq "--cluster");
}
# Remove leading dollar sign
if ( $volcheck =~ /\$/)
{
substr($volcheck, 0, 1) = "";
}
if ($volcheck)
{
$cmd = "cat $ENV{'TRAF_HOME'}/sql/scripts/sq_tse.create | grep mkdir | egrep \'$volcheck\\b\'";
$tsevols = `$cmd`;
chomp($tsevols);
$cmd = "cat $ENV{'TRAF_HOME'}/sql/scripts/sq_ase.create | grep mkdir | egrep \'$volcheck\\b\'";
$asevols = `$cmd`;
chomp($asevols);
}
else
{
$tsevols = `cat $ENV{'TRAF_HOME'}/sql/scripts/sq_tse.create | grep mkdir`;
$asevols = `cat $ENV{'TRAF_HOME'}/sql/scripts/sq_ase.create | grep mkdir`;
}
# Handle cluster case - we will use $SQ_PDSH to run dbcheck on each node,
# checking the volumes that are stored on that node
if ($tsevols =~ /pdsh/ || $asevols =~ /pdsh/)
{
$tsevols =~ s/\'//g;
$asevols =~ s/\'//g;
if (!$cluster)
{
print "\nPlease be patient, this may take awhile...\n\n";
do_pdsh($tsevols) if ($tsevols && $g_dotse);
do_pdsh($asevols) if ($asevols && $g_doase);
$pdshres =~ s/n[0-9]+: //g;
print "\nRESULTS:\n";
print "$pdshres\n";
exit (0);
}
}
# Volume specified on command line not found in sq_*se.create
if ($volcheck && ($tsevols eq "" && $asevols eq ""))
{
print "You specified volume \$$volcheck, but this volume wasn't found in the SE creation scripts...\n";
exit (1);
}
print "\nPlease be patient, this may take awhile...\n\n" if (!$cluster);
process_vol($tsevols) if ($tsevols);
process_vol($asevols) if ($asevols);
print_results();
}
main();