# $Header: blkcorrupt.tcl 29-mar-99.02:55:23 dholail Exp $
#
# copyright (c) 1999 by the Oracle Corporation
#
# NAME:
#
#  blkcorrupt.tcl : Event tcl file that checks from data block corruption 
#     errors that exist in the alert file
#
# ARGUMENTS:
#           argv(0) == connect string
#
# RETURN:
#           $CLEAR_EVENT or
#           $NO_EVENT or
#           $ALERT_EVENT
#
# OUTPUT:
#           The name of the segment which contains the corrupted data block
#
# $Log:  $
# Revision 1.2  1998/02/12  groyal
# improved error messages issued for script evaluation failures
#
# Revision 1.1  1998/01/14  groyal
# Initial revision
#


# Event definition
oradefine event /oracle/rdbms/fault/blkcorrupt description=VOC-01299 \
report=VOC-01300
oraarguments connect_str 
oravardesc connect_str oracle_signon
oraresults segments filenums blocknums reasons
oravardesc segments string
oravardesc filenums unsigned
oravardesc blocknums unsigned
oravardesc reasons string
oradefine end


# Initialize global variables
#comment out to fix bug#606739
#set last_report $NO_EVENT
set output ""
oraeventpersist last_alert_size -1


# The main event checking functions
proc EvalEvent {} {


    # Declare globals we will use
    #
    global argv last_report output last_alert_size 
    global SCRIPT_FAIL CLEAR_EVENT NO_EVENT WARNING_EVENT ALERT_EVENT
    global oramsg env


    # initialize the return code and output
    set ret_code $NO_EVENT
    set output ""
    set err ""
    set alertfile ""

    # set alert error to watch for corrupted data block error
# ORA-01157, cannot identify/lock data file string - see DBWR trace file
# ORA-01578, ORACLE data block corrupted (file # string, block # string)
# ORA-27048, skgfifi: file header information is invalid
    set alert_errors {ORA-01157 ORA-01578 ORA-27048}

    # get the location of the alert file    
    if {[catch {set alertfile [ALERTFILE]} err]} {
	lappend output $err
        if {$last_report == $SCRIPT_FAIL} {
	    return $NO_EVENT
        } else {
	    set last_report $SCRIPT_FAIL
	    return $SCRIPT_FAIL
        }
    }

    # during initialization, set the alert file size
    if {$last_alert_size == -1} {
        if { [file exists $alertfile] } {
   	    if {[catch {set last_alert_size [file size $alertfile]} err]} {
	        lappend output [format [msgtxt [NETWORK] nms 1005] blkcorrupt.tcl] 
	        lappend output $err
	        if {$last_report == $SCRIPT_FAIL} {
		    return $NO_EVENT
       	        } else {
		    set last_report $SCRIPT_FAIL
		    return $SCRIPT_FAIL
	        }
	    }
        } else {
            set last_alert_size 0
        }
        return $NO_EVENT
    }

    # check for the existence of the alert file
    if { ![file exists $alertfile] } {
        ORATCL_DEBUG "blkcorrupt : $oramsg(oraobject) : [oratime] : $alertfile does not exist"
        return $NO_EVENT
    }

    # get the new alert file size
    if {[catch {set current_alert_size [file size $alertfile]} err]} {
        lappend output [format [msgtxt [NETWORK] nms 1005] blkcorrupt.tcl] 
        lappend output $err
        if {$last_report == $SCRIPT_FAIL} {
	    return $NO_EVENT
        } else {
	    set last_report $SCRIPT_FAIL
	    return $SCRIPT_FAIL
        }
    }

    # print out event trace info 
    ORATCL_DEBUG "blkcorrupt : $oramsg(oraobject) : [oratime] : $alertfile, current_size = $current_alert_size"


    # must be a new alert log
    if {$last_alert_size > $current_alert_size} {
        ORATCL_DEBUG "alert : $oramsg(oraobject) : [oratime] : $alertfile looks new : last_size = $last_alert_size, current_size = $current_alert_size"
        set last_alert_size 0
    }

    # check alert file for new errors
    if {$last_alert_size != $current_alert_size} {
	if {[catch {set fd [open $alertfile r]} err]} {
            lappend output [format [msgtxt [NETWORK] nms 1005] blkcorrupt.tcl] 
	    lappend output $err
	    if {$last_report == $SCRIPT_FAIL} {
	        return $NO_EVENT
            } else {
	        set last_report $SCRIPT_FAIL
	        return $SCRIPT_FAIL
	    }
    	} else {		        
            if {[catch {seek $fd $last_alert_size start} err]} {
                lappend output [format [msgtxt [NETWORK] nms 1005] blkcorrupt.tcl] 
		lappend output $err
                catch {close $fd} err
	    	if {$last_report == $SCRIPT_FAIL} {
	            return $NO_EVENT
	        } else {
		    set last_report $SCRIPT_FAIL
	            return $SCRIPT_FAIL
	    	}
    	    }
	}

        while {[gets $fd line] >= 0} {
            set error_found 0
            foreach error $alert_errors {
                if {[string first $error $line] >= 0} {
                    set error_found 1
                    ORATCL_DEBUG "blkcorrupt : $oramsg(oraobject) : [oratime] : error $error found, line : $line"
                    set ret_code $ALERT_EVENT
                    lappend reasons $line
                    break
                }
            }

            if { $error_found == 1 } {
                continue
            }
        }
        catch {close $fd} err
    }
    set last_alert_size $current_alert_size

    # clear the event if script failed last time
    if { $ret_code == $NO_EVENT && $last_report == $SCRIPT_FAIL } {
        set last_report $CLEAR_EVENT
        return $CLEAR_EVENT
    }

    # return
    # this event triggers even if it's already triggered if new errors
    # are present in the alert file
    if { $ret_code != $NO_EVENT } {
        lappend output $reasons
        ORATCL_DEBUG "blkcorrupt : $oramsg(oraobject) : [oratime] : MESSAGE - $ret_code, $output"
    }
    return $ret_code

}

