core-extra/gui/exceptions.tcl

214 lines
6.7 KiB
Tcl

array set g_exceptions {}
global execMode
if { $execMode == "interactive" } {
set g_img_cel [image create photo -file $CORE_DATA_DIR/icons/tiny/cel.gif]
}
set g_cel_blink_state "off"
# receive an exception into the g_exceptions array from an Exception Message
proc receiveException { valuelist } {
global g_exceptions EXCEPTION_LEVELS execMode
set idx [expr {1 + [array size g_exceptions]}]
array set g_exceptions [list $idx $valuelist]
array set vals $valuelist
# print exception message on stdout if in batch mode
if { $execMode == "batch" } {
puts "\nFrom $vals(src): $vals(txt)"
# Abort the session if a fatal exception is reported
if { $vals(level) <= [lsearch -exact $EXCEPTION_LEVELS "FATAL" ] } {
global g_current_session g_abort_session
set g_abort_session 1
}
}
# exceptions with level ERROR or FATAL will throw the CEL
if { $vals(level) <= [lsearch -exact $EXCEPTION_LEVELS "ERROR"] } {
throwCEL false
if { $vals(level) <= [lsearch -exact $EXCEPTION_LEVELS "FATAL" ] } {
blinkCEL start
}
}
}
# turn on/off the CEL in the bottom right indicator area
proc throwCEL { clear } {
global execMode
if { $execMode != "interactive" } { return }
global g_img_cel
if { $clear } {
.bottom.indicators configure -image "" -width 5
} else {
if { [.bottom.indicators cget -image] == "" } {
.bottom.indicators configure -image $g_img_cel -width 42
}
}
}
# blink the CEL on and off for fatal errors
proc blinkCEL { cmd } {
global execMode
if { $execMode != "interactive" } { return }
# keep track of state so this can be called multiple times
global g_cel_blink_state
if { $cmd == "start" } {
if { $g_cel_blink_state != "off" } { return } ;# already on
set g_cel_blink_state "on"
} elseif { $cmd == "stop" } {
if { $g_cel_blink_state != "on" } { return } ;# already off
set g_cel_blink_state "off"
}
if { $g_cel_blink_state == "off" } {
throwCEL true
return
}
if { [.bottom.indicators cget -image] == "" } {
set clear false ;# CEL is off, turn it on
} else {
set clear true ;# CEL is on, turn it off
}
throwCEL $clear
after 750 blinkCEL "blink"
}
# clear the g_exceptions array and the CEL
proc clearExceptions { tree txt } {
global g_exceptions
array unset g_exceptions
array set g_exceptions {}
if { $tree != "" } {
exceptionsPopulateTree $tree $txt
}
}
# show the CEL dialog for viewing a list of exceptions
proc popupExceptions {} {
global g_img_cel CORE_STATE_DIR
set w .popupExceptions
catch {destroy $w}
toplevel $w
wm transient $w .
wm title $w "CEL"
ttk::frame $w.top
ttk::label $w.top.icon -image $g_img_cel
ttk::label $w.top.lab -text "Check Emulation Light"
pack $w.top.icon $w.top.lab -side left -padx 4
pack $w.top -side top -padx 4 -pady 4
ttk::frame $w.mid
ttk::treeview $w.mid.tree -columns {time level node source} -show headings \
-yscroll "$w.mid.vsb set" -xscroll "$w.mid.hsb set"
ttk::scrollbar $w.mid.vsb -orient vertical -command "$w.mid.tree yview"
ttk::scrollbar $w.mid.hsb -orient horizontal -command "$w.mid.tree xview"
pack $w.mid -side top -fill both -expand true -padx 4 -pady 4
grid $w.mid.tree $w.mid.vsb -in $w.mid -sticky nsew
grid $w.mid.hsb -in $w.mid -sticky nsew
grid column $w.mid 0 -weight 1
grid row $w.mid 0 -weight 1
ttk::frame $w.detail
text $w.detail.txt -height 10 -yscrollcommand "$w.detail.vsb set"
ttk::scrollbar $w.detail.vsb -orient vertical -command "$w.detail.txt yview"
pack $w.detail -side top -fill both -expand true -padx 4 -pady 4
grid $w.detail.txt $w.detail.vsb -in $w.detail -sticky nsew
grid column $w.detail 0 -weight 1
grid row $w.detail 0 -weight 1
bind $w.mid.tree <<TreeviewSelect>> \
"exceptionSelect $w.mid.tree $w.detail.txt"
ttk::frame $w.btn
set clearhicmd "drawNodeCircle {} {} {} {} excphi"
set clearexcpcmd "clearExceptions $w.mid.tree $w.detail.txt"
set closecmd "destroy $w; $clearhicmd"
bind $w <Key-Escape> $closecmd
ttk::button $w.btn.reset -text "Reset CEL" \
-command "throwCEL true; blinkCEL stop; $clearhicmd; $clearexcpcmd"
ttk::button $w.btn.log -text "View core-daemon log" \
-command "popupFileView $CORE_STATE_DIR/log/core-daemon.log"
ttk::button $w.btn.nlog -text "View node log" -state disabled
ttk::button $w.btn.close -text "Close" -command $closecmd
pack $w.btn.reset $w.btn.log $w.btn.nlog $w.btn.close -side left
pack $w.btn -side top -padx 4 -pady 4
# populate treeview
set widths { 150 40 40 60 }; set i 0
foreach col {time level node source} {
$w.mid.tree heading $col -text $col
set width [lindex $widths $i]; incr i
$w.mid.tree column $col -width $width
}
exceptionsPopulateTree $w.mid.tree $w.detail.txt
}
# populate the given TreeView with a list of exceptions from g_exceptions
proc exceptionsPopulateTree { tree txt } {
global g_exceptions
set items [$tree children {}]
$tree delete $items
$txt delete 0.0 end
foreach idx [lsort -integer [array names g_exceptions]] {
array set vals $g_exceptions($idx)
set level [exceptionLevelText $vals(level)]
$tree insert {} end -id $idx \
-values [list $vals(date) "$level ($vals(level))" \
$vals(num) $vals(src)]
}
}
# user has clicked on an exception from the TreeView, display the details
proc exceptionSelect { tree txt } {
global g_exceptions g_current_session
set idx [$tree selection]
set btn .popupExceptions.btn.nlog
$txt delete 0.0 end
drawNodeCircle "" "" "" "" excphi
if { ![info exists g_exceptions($idx)] } {
puts "missing exception data"
return
}
array set vals $g_exceptions($idx)
$txt insert end "DATE: $vals(date)\n"
set level [exceptionLevelText $vals(level)]
$txt insert end "LEVEL: $level ($vals(level))\n"
set node ""
if { $vals(num) >= 0 } {
set node "n$vals(num)"
global $node
if { [info exists $node] } {
drawNodeCircle $node 30 red excphi ""
set node [getNodeName $node]
$btn configure -command \
"popupFileView /tmp/pycore.$g_current_session/$node.log"
$btn state !disabled
} else {
$btn state disabled
}
} else {
$btn state disabled
}
$txt insert end "NODE: $vals(num)\t($node)\n"
$txt insert end "SESSION: $vals(sess)\n"
$txt insert end "SOURCE: $vals(src)\n"
$txt insert end "\n$vals(txt)\n\n"
if { $vals(opaque) != "" } {
$txt insert end "\nOPAQUE: $vals(opaque)\n\n"
}
}
proc exceptionLevelText { level } {
global EXCEPTION_LEVELS ;# from api.tcl
if { $level < 0 || $level >= [llength $EXCEPTION_LEVELS] } {
return "UNKNOWN"
} else {
return [lindex $EXCEPTION_LEVELS $level]
}
}