#!/usr/bin/perl -w #================================================================================================== # # Name: master_event.plx # Description: # This program will monitor all event's reported by the Informix Engine and log # and will automatically back up logical logs as they fill. # This program will also look at the free redo logs and send an email alert (either # email or pager number) if the number of free logs =< total logs. # This program requires ESQL-C libraries, Perl DBI and DBD::Informix # # Who Date Ver Description # --------------- --/--/-- -.- ------------------------------------- # Albert L. Smith 03/17/03 1.0 Created # #================================================================================================== # Global variables here! require 5.8.0; use strict; use DBI; $| = 1; my($subj,$INFORMIXSERVER,$dirdate,$Log) = undef; my($severity,$class,$msg,$add_text,$file,$dbh) = undef; #================================================================================================== # Environment variables here! #================================================================================================== $ENV{INFORMIXDIR} = "/informix"; $ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin:/usr/ucb:/etc:/informix/bin"; #================================================================================================== # Start Main Module #================================================================================================== &do_init; if($class eq 1) { print Log "## Error: Table Failure\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 2) { print Log "## Error: Index Failure\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 3) { print Log "## Error: Blob Failure\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 4) { print Log "## Error: Chunk Off-line, Mirror is active and On-line\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 5) { print Log "## Error: Dbspace is Off-line\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 6) { print Log "## Error: Internal Subsystem Failure\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 7) { print Log "## Error/Warning: Server Initialization Failure\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 8) { print Log "## Error: Physical Restore Failure\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 9) { print Log "## Error: Physical Recovery Failure\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 10) { print Log "## Error: Logical Recovery Failure\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 11) { print Log "## Error: Cannot open Chunk\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 12) { print Log "## Error: Cannot open Dbspace\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 13) { print Log "## Info: Performance Improvement Possible\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 14) { print Log "## Error: Database Failure\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 15) { print Log "## Error: Data Replication Failure\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 16) { print Log "## Info: Archive Complete\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 17) { print Log "## Failure/Warning: Archive Aborted\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 18) { print Log "## Info: Logical Log Backup Complete\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 19) { print Log "## Error: Logical Log Backup Aborted\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 20) { print Log "## Error: All Logical Logs Are Full\n"; &do_term(5); } elsif($class eq 21) { print Log "## Error: Server Resource Overflow\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 22) { print Log "## Warning: Long Transaction Detected\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 23) { print Log "## Info: Logical Log Complete\n"; if($severity > 3) { &do_term(5); } else { &connect_db; &lock_backup; &do_backup; &check_free; &unlock_backup; &disconnect_db; } } elsif($class eq 24) { print Log "## Error: Unable to Allocate Memory (Malloc)\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 25) { print "Class not defined.\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 26) { print Log "## Info: Dynamically Added Logical Log\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 27) { print Log "## Warning: Logical Log File Required\n"; if($severity > 3) { &do_term(5); } } elsif($class eq 28) { print Log "## Warning: No Space for Logical Log File\n"; if($severity > 3) { &do_term(5); } } else { print "Class not defined.\n"; if($severity > 3) { &do_term(5); } } close(Log); #================================================================================================== # Start sub function definitions #================================================================================================== sub do_init { ($severity,$class,$msg,$add_text,$file) = @ARGV; $INFORMIXSERVER = $ENV{INFORMIXSERVER}; chop( my $Sdate = `date +%m%d%y-%H:%M`); chop( my $date = `date +Date%m%d%yTime%H%M`); chop( $dirdate = `date +%m_%d_%y`); $subj = "logical0"."_"."$date"; $Log = "/$ENV{INFORMIXDIR}/logs/masterEvent.$INFORMIXSERVER.log"; open(Log, ">>$Log"); print Log "***********************************************************\n"; print Log "*** Master Event program called @ $Sdate ***\n"; print Log "***********************************************************\n"; print Log "** Severity: $severity\n"; print Log "** Class: $class\n"; print Log "** Message: $msg\n"; print Log "** Add_Text: $add_text\n"; print Log "** File: $file\n"; print Log "** - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"; print Log "** Program Defined Information Below:\n"; return; } #================================================================================================== sub connect_db { $dbh = DBI->connect("dbi:Informix:sysmaster",,, { RaiseError => 1, PrintError => 1 }); print Log "## Successfully connected to sysmaster\n"; return; } #================================================================================================== sub lock_backup { my ($name,$stat,$cnt) = undef; chdir("/logical0/$INFORMIXSERVER") || &do_term(2); unless(-d $dirdate) { mkdir("$dirdate",0770) || &do_term(0); print Log "## Created directory /logical0/$INFORMIXSERVER/$dirdate\n"; } opendir(DIR,"."); while($name = readdir("DIR")) { if($name eq "logical0") { $stat = 1; print Log "## logical0 file exists.\n"; } } closedir(DIR); if($stat) { $cnt = &check_ontape_thread; } if($stat && $cnt >= 1) { &do_term(1); } else { unlink("logical0"); system("touch logical0"); chmod (0660, "logical0"); } return; } #================================================================================================== sub check_ontape_thread { my $sth = undef; my($cnt) = 0; my $sql_lock = "Select count(*) from systhreads where th_name = 'ontape'"; $sth = $dbh->prepare($sql_lock); $sth->execute(); $cnt = $sth->fetchrow(); return($cnt); } #================================================================================================== sub do_backup { my ($line,$lognum,$stat) = undef; my $string = "This tape contains the following logical logs:"; my $cmd = "echo '\n n\n' \| ontape -a"; open(CMD, "$cmd |"); while ($line = ) { chop($line); if($line =~ /$string/) { $stat = 1; next; } if($stat) { $lognum = "$line"; $lognum =~ s/\s+//g; $stat = undef; } } close(CMD); $subj .= "Logs"."$lognum"; system("mv logical0 $dirdate/$subj"); print Log "## $string $lognum\n"; return; } #================================================================================================== sub unlock_backup { print Log "## Compressing logical log and Removing lock file\n"; chdir("$dirdate"); system("compress $subj"); return; } #================================================================================================== sub check_free { my($logtot,$logfree,$logused,$sth1,$sth2,$sth3,$lowerlimit) = undef; my $sql1 = "Select count(*) From syslogs"; my $sql2 = "Select count(*) From syslogs Where is_backed_up = 1"; my $sql3 = "Select count(*) From syslogs Where is_backed_up = 0"; $sth1 = $dbh->prepare($sql1); $sth2 = $dbh->prepare($sql2); $sth3 = $dbh->prepare($sql3); $sth1->execute(); $sth2->execute(); $sth3->execute(); $logtot = $sth1->fetchrow(); $logfree = $sth2->fetchrow(); $logused = $sth3->fetchrow(); print Log "## Logical Logs Free: $logfree\n"; if($logtot != ($logfree + $logused)) { &do_term(3); } $lowerlimit = ($logtot / 2); if($logfree <= $lowerlimit) { &do_term(4,$logfree,$logtot); } return; } #================================================================================================== sub disconnect_db { $dbh->disconnect; return; } #================================================================================================== sub do_term { my $stat = $_[0]; my $info1 = $_[1]; my $info2 = $_[2]; my $mesg = undef; if($stat eq "0") { $mesg = "$ENV{INFORMIXSERVER} ALERT: Cannot create date directory."; print Log "## $mesg\n"; exit -0; } elsif($stat eq "1") { print Log "## Current logical0 backup running. Exiting and doing nothing.\n"; &check_free; exit -1; } if($stat eq "2") { $mesg = "$INFORMIXSERVER ALERT: Cannot cd to /logical0/"; print Log "## $mesg\n"; exit -2; } elsif($stat eq "3") { $mesg = "Logical Log count isn't sane, Free Logs + Used Logs "; $mesg .= "doesn't = Total Logs.\n"; print Log "## $mesg\n"; &check_free; exit -3; } elsif($stat eq "4") { $mesg = "*** $INFORMIXSERVER ALERT: Only $info1 logical logs "; $mesg .= "free out of $info2 Total Logs!!!"; print Log "## $mesg\n"; print Log "## SENDING PAGING TO ONCALL DBA\n"; system("/usr/bin/echo \"$mesg\" | /usr/sbin/sendmail xxxxxxxxxx\@skytel.com"); exit -4; } elsif($stat eq "5") { $mesg = "## $INFORMIXSERVER ALERT: A severity level $severity has occured.\n"; $mesg .= "## CLASS: $class\n"; $mesg .= "## MESSAGE: $msg\n"; print Log "## SENDING PAGING TO ONCALL DBA\n"; system("/usr/bin/echo \"$mesg\" | /usr/sbin/sendmail xxxxxxxxxx\@skytel.com"); exit -5; } return; } #==================================================================================================