#!/usr/bin/perl5 # informix 5.x logical log tape validator #written after some very painful experiences with informix recovery # This software is supplied without any warrenty whatsover # If you find it useful use it otherwise dont blame me # J.Clutterbuck Siemens Business Services 11th June 1997 $usage="logtape_validate.pl [-v] ltapedev\n"; #check for optional -v (verbose) argument if ( $ARGV[0] eq "-v" ) { $verbose=1; shift @ARGV; } else { $verbose=0; } if ( $#ARGV != 0 ) { die $usage; } $LOGTAPE=$ARGV[0]; #get environment variables $TBCONFIG=$ENV{'TBCONFIG'} || die "Cannot evaluate TBCONFIG environment variable\n"; $INFORMIXDIR=$ENV{'INFORMIXDIR'} || die "Cannot evaluate INFORMIXDIR environment variable\n"; #open TBCONFIG file open(TBCONFIG,"<$INFORMIXDIR/etc/$TBCONFIG") || die "cannot open $INFORMIXDIR/etc/$TBCONFIG for reading\n"; #read and look for LOGSIZE & LTAPEBLK print "Getting logical log tape details from $INFORMIXDIR/etc/$TBCONFIG\n"; while (<TBCONFIG>) { if ( /^LOGSIZE\s+([0-9]+)\s+/ ) { $LOGSIZE=$1; } elsif ( /^LTAPEBLK\s+([0-9]+)\s+/ ) { $LTAPEBLK=$1; } } close(TBCONFIG); if ( ! $LOGSIZE || ! $LTAPEBLK ) { die "Cannot establish LOGSIZE or LTAPEBLK from $INFORMIXDIR/etc/$TBCONFIG\n"; } #open the log file open(LOGTAPE,"<$LOGTAPE") || die "Cannot open $LOGTAPE\n"; print "Reading tape: $LOGTAPE\n"; #read each line $found=0; $num=0; $rec_bytes = $LTAPEBLK * 1024; #number of bytes per tape record $log_bytes = $LOGSIZE * 1024; #number bytes per log file $num_per_log = 1 + int(($log_bytes-1)/$rec_bytes); #number of records per log $got_err=0; $found_hdr=0; $curr_logno=0; $first_logno=0; $prev_logno=0; $recno=0; nextlog: while(1) { #read all the records per log file $found_log=0; foreach $b ( 1 .. $num_per_log ) { $numread=sysread(LOGTAPE,$logbuf,$rec_bytes); ++$recno; if ( $numread != $rec_bytes ) { if ( $found_hdr && $curr_logno ) { print "ERROR $numread BYTES READ INSTEAD OF $rec_bytes IN RECORD $recno - END OF TAPE?\n" if $verbose; } else { print "ERROR $numread BYTES READ INSTEAD OF $rec_bytes IN RECORD $recno - NOT A LOG FILE TAPE\n" if $verbose; $got_err=1; } last nextlog; } #look at header(s) if first record per log file if ( $b >= 1 ) { $hdr_offset=0; testhdr: while(1) { #unpack header from first 2048 bytes $header=substr($logbuf,$hdr_offset,2048); ($h1)=unpack "i4",$header; #look for tape header if ( $h1 == -1 ) { printf "TAPE HEADER (%d) record %4d offset %5d\n",$h1,$recno,$hdr_offset if $verbose; if ( ++$found_hdr > 1 || $hdr_offset || $recno != 1) { print "*** ERROR - DUPLICATE OR NOT IN FIRST BLOCK ***\n"; $got_err=1; last nextlog; } } elsif ( $h1 == -4 ) { ++$curr_logno; ($log_number)=unpack "i4",substr($header,16,4); $message=''; if ( $curr_logno == 1 && ! $found_hdr ) { $message.="*** ERROR - NO TAPE HEADER ***"; $got_err=1; } if ( ++$found_log > 1 ) { $message.="*** ERROR - LOG $found_log IN BLOCK ***"; $got_err=1; } #check for log sequence and remeber first/last if ( $prev_logno ) { if ( $log_number != $prev_logno+1 ) { $message.="*** ERROR - BAD LOG SEQUENCE $prev_logno - $curr_logno ***"; $got_err=1; } } elsif ( ! $first_logno ) { $first_logno=$log_number; } $prev_logno=$log_number; printf "Log Header (%d) record %4d offset %5d - LOGFILE: %6d %s\n",$h1,$recno,$hdr_offset,$log_number,$message if $verbose; } elsif ( $h1 > -10 && $h1 < 0 ) { printf "???? Header (%d) record %4d offset %5d\n",$h1,$recno,$hdr_offset if $verbose; } else { last testhdr; } #look at next bit of block $hdr_offset+= 2048; } } } } close(LOGTAPE); if ( $got_err ) { print "\n*** ERRORS FOUND *** - Tape contains logical logs: $first_logno - $prev_logno\n"; } else { print "\nNo Errors - Tape contains logical logs: $first_logno - $prev_logno\n"; } #eof