# $Header: sysstatd.tcl 31-mar-00.10:50:11 sgrover Exp $
#
# copyright (c) 1999 by the Oracle Corporation
#
# NAME:
#
#  sysstatd.tcl : Event tcl file that checks if the delta value of the 
#                 specified v$sysstat parameter is too high 
#
# ARGUMENTS:
#           argv(0) == no of occurrance
#           argv(1) == threshold value for alert
#           argv(2) == threshold value for warning
#           argv(3) == paramter name
#
# RETURN:
#           $SCRIPT_FAIL or
#           $CLEAR_EVENT or
#           $NO_EVENT or
#           $WARNING_EVENT or
#           $ALERT_EVENT
#
# OUTPUT:
#           The current parameter value
#
# $Log:  $
# Revision 1.6  1996/06/24  23:55:09  yliu
# fixed bug 370148
#
# Revision 1.5  1996/02/07  01:49:31  yliu
# use character set conversion
#
# Revision 1.4  1996/01/10  01:36:56  yliu
# use message file
#
# Revision 1.3  1995/10/25 01:43:43  yliu
# add connect string to the parameter list
#
# Revision 1.2  1995/10/18  22:44:45  yliu
# moved the init code into EvalEvent
#
# Revision 1.1  1995/10/14  00:18:47  yliu
# Initial revision
#

# Event definition
oradefine event /oracle/rdbms/perf/sysstatd description=VOC-01221 \
report=VOC-01222
oraarguments connect_str no_occurrence alert_threshold warning_threshold parameter_name
oravardesc connect_str oracle_signon
oravardesc no_occurrence unsigned default=3 message=VOC-01223
oravardesc alert_threshold number message=VOC-01224
oravardesc warning_threshold number message=VOC-01225
oravardesc parameter_name string message=VOC-01226
oraresults stat_name delta
oravardesc stat_name string
oravardesc delta string
oradefine end


# Initialize global variables
#comment out to fix bug#606739
#set last_report $CLEAR_EVENT
set output ""
set no_occurrence 0
set initial 1
set prev_value 0
set startup_time ""

# The main event checking functions
proc EvalEvent {} {


    # Declare globals we will use
    global argv last_report output no_occurrence initial
    global SCRIPT_FAIL CLEAR_EVENT NO_EVENT WARNING_EVENT ALERT_EVENT
    global oramsg prev_value startup_time


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


    set connect [format "%s@%s" [lindex $argv 0] $oramsg(oraobject)]
    # connect to the database and open a cursor
    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
        }
    }

    # Get current value
    set stat_name [lindex $argv 4]

    set sql {select value from v$sysstat where name = }
    set sql [concat $sql [format "'%s'" $stat_name]]

    if {[catch {orasql $cur $sql}] == 1} {
        lappend output [convertout $oramsg(db_characterset) \
        $oramsg(errortxt)] $sql
        catch {oraclose $cur} err
        catch {oralogoff $lda} err
        lappend output $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
        }
    }

    if {$oramsg(rows) == 0} {
        lappend output [msgtxt [NETWORK] nms 1008] $sql
        catch {oraclose $cur} err
        catch {oralogoff $lda} err
        lappend output $err
        if {$last_report == $SCRIPT_FAIL} {
            return $NO_EVENT
        } else {
            set last_report $SCRIPT_FAIL
            return $SCRIPT_FAIL
        }
    }
    set curr_value [lindex $row 0]

    # checking the start time with the previous start time,
    # just to make sure we're talking about the same run ... 
    set sql {alter session set NLS_DATE_FORMAT = 'HH24:MI:SS, MM/DD/YYYY'}

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

    set sql {select startup_time from v$instance }

    if {[catch {orasql $cur $sql}] == 1} {
        lappend output [convertout $oramsg(db_characterset) \
        $oramsg(errortxt)] $sql
        catch {oraclose $cur} err
        catch {oralogoff $lda} err
        lappend output $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
        }
    }

    if {$oramsg(rows) == 0} {
        lappend output [msgtxt [NETWORK] nms 1008] $sql
        catch {oraclose $cur} err
        catch {oralogoff $lda} err
        lappend output $err
        if {$last_report == $SCRIPT_FAIL} {
            return $NO_EVENT
        } else {
            set last_report $SCRIPT_FAIL
            return $SCRIPT_FAIL
        }
    }
    set curr_startup_time [lindex $row 0]

    catch {oraclose $cur} err
    catch {oralogoff $lda} err

    # During initialization, copy current values to previous values
    if {$initial == 1} {
        set startup_time $curr_startup_time
        set prev_value $curr_value
        set initial 0
        return $NO_EVENT
    }

    # check startup_time
    if {[string compare $startup_time $curr_startup_time] != 0} {
        ORATCL_DEBUG "sysstatd: instance restarted at $curr_startup_time"
        set startup_time $curr_startup_time
        set prev_value $curr_value
        return $NO_EVENT
    }

    # calculate delta 
    set curr_value_float [format "%f" $curr_value]
    set prev_value_float [format "%f" $prev_value]
    set delta [expr $curr_value_float - $prev_value_float]

    # consider negative delta value for some stats
    if {([string compare $stat_name "logons current"] == 0) ||
        ([string compare $stat_name "opened cursors current"] == 0)} {
        set neg_delta [expr $prev_value_float - $curr_value_float]
        if {$neg_delta > $delta} {
            ORATCL_DEBUG "sysstatd : $oramsg(oraobject) : [oratime] : -$neg_delta"
            ORATCL_DEBUG "sysstatd: '$stat_name' get negative delta value"
            set delta $neg_delta
        }
    }

    set prev_value $curr_value

    # print out event trace info 
    ORATCL_DEBUG "sysstatd : $oramsg(oraobject) : [oratime] : $curr_value, $delta"

    # Check for alert and warning threshold
    if {$delta >= [lindex $argv 2]} {
        if {$no_occurrence < [expr [lindex $argv 1] - 1]} {
            incr no_occurrence
        } else {
            set ret_code $ALERT_EVENT
            set delta [format "%.0f" $delta]
            lappend output $stat_name $delta
        }

    } elseif {$delta >= [lindex $argv 3]} {
        if {$no_occurrence < [expr [lindex $argv 1] - 1]} {
            incr no_occurrence
        } else {
            set ret_code $WARNING_EVENT
            set delta [format "%.0f" $delta]
            lappend output $stat_name $delta
        }

    } else {
        set no_occurrence 0
    } 

    # return
    if {$last_report == $ret_code} {
        return $NO_EVENT
    } else {
        ORATCL_DEBUG "sysstatd : $oramsg(oraobject) : [oratime] : MESSAGE - $ret_code, $output"
        set last_report $ret_code
        return $ret_code 
    }
}

