# $Header: archhung.tcl 29-mar-99.02:42:31 dholail Exp $
#
# copyright (c) 1999 by the Oracle Corporation
#
# NAME:
#
#  archhung.tcl : Event tcl file that checks for errors indicating the
#     archiver is hung that exist in the alert file
#
# ARGUMENTS:
#           argv(0) == connect string
#
# RETURN:
#           $CLEAR_EVENT or
#           $NO_EVENT or
#           $WARNING_EVENT or
#           $ALERT_EVENT
#
# OUTPUT:
#           The archiver hung error messages from the alert files.
# $Log:  $
# Revision 1.1  1998/01/22  groyal
# Initial revision


# Event definition
oradefine event /oracle/rdbms/fault/archhung description=VOC-01297 \
report=VOC-01298
oraarguments connect_str
oravardesc connect_str oracle_signon
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 ""

    # Check if the archive mode is on
    set connect [format "%s@%s" [lindex $argv 0] $oramsg(oraobject)]
    if {[catch {oralogon $connect} lda]} {
        lappend output [msgtxt [RDBMS] ora $oramsg(rc)] ""
        if {$last_report == $SCRIPT_FAIL} {
            return $NO_EVENT
        } else {
            set last_report $SCRIPT_FAIL
            return $SCRIPT_FAIL
        }
    }
    if {[catch {set cur [oraopen $lda]} err]} {
	lappend output $err
        catch {oralogoff $lda} err
        if {$last_report == $SCRIPT_FAIL} {
            return $NO_EVENT
        } else {
            set last_report $SCRIPT_FAIL
            return $SCRIPT_FAIL
        }
    }

    set sql {select log_mode from v$database}
    if {[catch {orasql $cur $sql}]} {
        lappend output [convertout $oramsg(db_characterset) \
            $oramsg(errortxt)] $sql
        catch {oraclose $cur} err
        catch {oralogoff $lda} err
	if {$last_report == $SCRIPT_FAIL} {
            return $NO_EVENT
        } else {
            set last_report $SCRIPT_FAIL
            return $SCRIPT_FAIL
        }
    }

    if {[catch {set row [orafetch $cur]} err]} {
	lappend output $err
        catch {oraclose $cur} err
        catch {oralogoff $lda} err
        if {$last_report == $SCRIPT_FAIL} {
            return $NO_EVENT
        } else {
            set last_report $SCRIPT_FAIL
            return $SCRIPT_FAIL
        }
    }

    # log off
    catch {oraclose $cur} err
    catch {oralogoff $lda]} err

    # verify database is operating in ARCHIVELOG mode
    if {[string compare [lindex $row 0] "ARCHIVELOG"] != 0} {
        if {$last_report == $SCRIPT_FAIL} {
            return $NO_EVENT
        } else {
            set last_report $SCRIPT_FAIL
            lappend output [msgtxt [NETWORK] nms 1012] ""
            return $SCRIPT_FAIL
        }
    }


    # set alert error to watch for the archiver hung error
    set alert_error "ORA-00257"
    
    # 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] archhung.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 "archung : $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] archhung.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 "archhung : $oramsg(oraobject) : [oratime] : $alertfile, $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_alert_size, $current_alert_size"
        set last_alert_size 0
    }


    # check 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] archhung.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] archhung.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} {
            if {[string first $alert_error $line] >= 0} {
                set ret_code $ALERT_EVENT
                break
            }
        }
        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 } {
        ORATCL_DEBUG "archhung : $oramsg(oraobject) : [oratime] : MESSAGE - $ret_code"
    }
    return $ret_code


}

