| #!/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(); |