# DDCrun.ctl: Oracle Database Diagnostics Collector (Data Collection) # $Id: DDCrun.ctl,v 1.10 2015/07/01 12:16:33 RDA Exp $ # ARCS: $Header: /home/cvs/cvs/RDA_8/src/scripting/lib/collect/DB/DDCrun.ctl,v 1.10 2015/07/01 12:16:33 RDA Exp $ # # Change History # 20150701 KRA Improve SQL target handling. =head1 NAME DB:DDCrun - Oracle Database Diagnostics Collector (Data Collection) =head1 DESCRIPTION This module executes the data collection part of the Oracle Database Diagnostics Collector. =cut use $[tgt] echo tput('bold'),'Collecting dumps/traces for Oracle Database processes ...',\ tput('off') # Initialization import $ORACLE_HOME,$ORACLE_SID import $DDC_ASH,$DDC_CMD,$DDC_EVT_SLP,$DDC_PID,$DDC_SLP,$DDC_TRC_SLP,$DDC_USR import @DDC_PID,%DDC_BGP,%DDC_DMP,%DDC_PRC,%DDC_SQL import $WAIT call setAbbr('DB_DDC_') call setPrefix(concat('t',localtime('%y%m%d%H%M'))) var $CPG = ${RUN.REQUEST.B_CALL_KSMCPG:false} var $DBC = not(getSqlTarget()->get_prelim) var $KIP = 0 var $PID = getPid() var $PRE = concat(${CUR.W_PREFIX},localtime('%y%m%d%H%M')) var $TOC = '%TOC%' var $TOP = '[[#Top][Back to top]]' var $sid = replace(concat('_',$ORACLE_SID),'[\_\W]+','_',true) var $CLR = concat('^DB_TMP_ddc(st|up)',$sid,'\.tmp$') var $REQ = concat('^DB_TMP_(ddcrq',$sid,'_(\d+).tmp)$') var $STA = concat('ddcst',$sid,'.tmp') var $WUP = catFile(${OUT.E},concat('DB_TMP_ddcup',$sid,'.tmp')) var ($TTL,@EVT,@HDR,@KIP,@TTL) = () # Load the common macros run DB:DBinfo() # --- Features ---------------------------------------------------------------- # Generic dumps/reports: # A Hang Analyze Dump # C Locking Contention Report # D Active Session History Dump # E Event Histogram # H Shared Pool (Heap) Dump # L Library Cache Dump # R Row Cache Dump # S System State Dump # W Session Wait Events Report # Process dumps/traces: # E Process Error Stack # F Process Open Files # L Process Dynamic Libraries # O Operating System Trace # P Process State Dump # S Process Stack # T 10046 Trace ## Unimplemented features: ## X export SCRIPT_LIST=`echo ${OPTARG} | sed "s/,/ /g"`;; ## $DDC_TEST_MODE # --- Process Control Macro Definitions --------------------------------------- # Create an execution indicator macro create_lock {var ($job,$grp,$pid,@txt) = @arg var $pre = setPrefix($job) var $lck = $[OUT]->add_report('e',concat($grp,$pid),0,'.tmp') if @txt call $lck->write(@txt) else call $lck->create call $lck->close call setPrefix($pre) return $lck } # Remove all execution indicators for a group macro delete_group {var ($job,$grp) = @arg var $pat = concat('DB_DDC_',$job,'_',$grp,'_?\d+\.tmp$') call purge('e',$pat,-1,0) } # Get the lock pattern macro get_lock {var ($job,$grp) = @arg return concat('^DB_DDC_',$job,'_',$grp,'(_)?(\d+)\.tmp$') } # Find running processes macro grep_lock {var ($job,$grp) = @arg var $pat = concat('^DB_DDC_',$job,'_',$grp,'_?\d+\.tmp$') return grepDir(${OUT.E},$pat,'i') } # Check the synchronization requirements macro check_wait {if get_wait(@arg) return sprintf('!!call kip(%d)',last) return '' } macro get_wait {var $txt = join('',@arg) import $KIP,$WAIT,@KIP keep $KIP,$WAIT,@KIP if $WAIT {incr $KIP var $KIP[$KIP] = $txt return $KIP } return 0 } # Synchronize the execution macro kip {var ($off) = @arg import $REQ,$STA,$WUP,@KIP keep $REQ,$STA,$WUP,@KIP var $txt = $KIP[$off] suspend report call dsp_event('Waiting on wake-up for ',$txt) var $abr = setAbbr('DB_TMP_') while true {# Touch the time stamp file output E,$STA write close # Check the presence of the wakeup file sleep 3 if ?testFile('f',$WUP) {call dsp_event('Waking up for ',$txt) break } # Detect a status request if grepDir(${OUT.E},$REQ,'if') {var ($req) = last var ($rpt,$pid) = match($req,$REQ,true) next expr('==',$pid,$prv) output >> E,$rpt write '- Pending on ',$txt close var $prv = $pid } } call setAbbr($abr) resume report } # --- Output Macro Definitions ------------------------------------------------ # Open the log report output >> e,log global $[log] = ${CUR.O_LAST} alias log = $[log]->write() alias hasLog = $[log]->has_output() call $[log]->unlink call log('---+!! ORADDC Collection Log') call log('---### ORADDC collection started at ',${RDA.T_LOCALTIME}) call log($TOC) # Start logging events macro begin_log {prefix $[log] call log('') call $[log]->close(true) } # Clone the log macro clone_log global $[log] = $[log]->clone # Display and log an event macro dsp_event {debug @arg call log_event(@arg) } macro DspEvent {var ($evt) = @arg import @EVT keep @EVT call dsp_event($EVT[$evt]) } # Display and log a line macro dsp_line {debug @arg call log(@arg) } # End logging events macro end_log {if hasLog(true) call log('') } # Log an event macro log_event call log(substr(${RDA.T_LOCALTIME},-8),': ',@arg) # --- Macro Definitions ------------------------------------------------------- # Check hanganalyze dump for suspicious sessions macro check_hanganalyze {call dsp_event('Checking hanganalyze dump for hangs and blockers ...') if grepFile($[log]->get_file(true),'hanganalyze.*\.trc','i') {# Identify the corresponding trace list (excluding duplicates) loop $lin (last) var $fil{value($lin)} = 1 # Treat all files var $pre = ' ' loop $fil (keys(%fil)) {# List 'in-hang' SIDs var %tbl = () loop $lin (grepFile($fil,'IN_HANG')) {var @tbl = split('\/',$lin) next !length($tbl[5]) var $tbl{concat($tbl[2],' (',$tbl[5],')')} = true } if keys(%tbl) {var @tbl = last call dsp_line() call dsp_event('Examining file: ',$fil) call dsp_event('The following "in hang" SIDs (O/S PIDs) found:') loop $lin (@tbl) call dsp_line($pre,$lin) call dsp_event('Consider running a process state dump for these ...') call dsp_line() } # List blocking SIDs var %tbl = () loop $lin (grepFile($fil,'LEAF')) {var @tbl = split('\/',$lin) next !length($tbl[5]) var $tbl{concat($tbl[2],' (',$tbl[5],')')} = true } if keys(%tbl) {var @tbl = last call dsp_line() call dsp_event('Examining file: ',$fil) call dsp_event('The following blocking SIDs (O/S PIDs) found:') loop $lin (@tbl) call dsp_line($pre,$lin) call dsp_event('Consider running a process state dump for these ...') } # List process dumps call dsp_line() call dsp_event('** If process traces have been generated') call dsp_event(' by hanganalyze the PIDs will appear below ...') var %tbl = () loop $lin (grepFile($fil,'^Dumping')) {if match($lin,'^.* (\d+)') {var ($pid) = last var $tbl{$pid} = true } } if keys(%tbl) {var @dmp = last call dsp_line() call dsp_event('The hanganalyze has already generated process dumps for \ the following:') var %tbl = () loop $lin (grepFile($fil,'^Dumping')) var $tbl{replace($lin,'Dumping','Dumped')} = 1 loop $lin (keys(%tbl)) call dsp_line($pre,$lin) call dsp_line() call dsp_line() call dsp_event('Trace/dump files generated by HANGANALYZE:') var $bdd = get_bdump() var $udd = get_udump() loop $pid (@dmp) {loop $trc (grepDir($udd,concat('_',$pid,'_.*\.trc$'),'inp')) call dsp_line($pre,$trc) loop $trc (grepDir($bdd,concat('_',$pid,'_.*\.trc$'),'inp')) call dsp_line($pre,$trc) } } else call dsp_event('The hanganalyze did not appear to generate any process \ dumps.') } } } # Collate produced traces macro collate_traces {import $LDD_PGM,$PFL_PGM,$TOP,$STK_PGM,$TRC_PGM # Stop event logging call end_log() call log($TOP) prefix $[log] {call log('---+ Trace File Summary') call log('**Note:** Some trace files may also contain other diagnostic types \ in addition to what indicated, depending on the combination of \ options selected.%BR% ') } # Define a macro retrieving reports macro find_traces {var ($pat) = @arg var ($pth,@lnk) = ($[log]->get_file(true)) call $[log]->close(true) loop $lin (grepFile($pth,$pat)) {var $fil = field(':\s+',2,$lin) if ?testFile('r',catFile(${OUT.E},$fil)) call push(@lnk,concat('[[',$fil,'][_blank][',$fil,']]')) } return @lnk } macro find_reports {var ($pth,@lnk) = ($[log]->get_file(true)) call $[log]->close(true) loop $lin (grepFile($pth,'Spooling to:')) {var $fil = field(':\s+',2,$lin) call push(@lnk,concat('[[',value($fil),'][_blank][',key($fil),']]')) } return @lnk } # Collate report files if find_reports() call log('|*Reports*|',join('%BR%',last),'|') # Collate stack traces if find_traces('Stack trace written to:') call log('|*Stack (',$STK_PGM,') Traces*|',join('%BR%',last),'|') if find_traces('Pfiles trace written to:') call log('|*Process Open Files (',$PFL_PGM,') Traces*|',join('%BR%',last),'|') if find_traces('Pldd trace written to:') call log('|*Process Dynamic Libraries (',$LDD_PGM,') Traces*|',\ join('%BR%',last),'|') # Collate O/S traces if find_traces('O/S trace written to:') call log('|*O/S (',$TRC_PGM,') Traces*|',join('%BR%',last),'|') # Collate Oracle dumps call $[log]->close(true) if grepFile($[log]->get_file(true),'Trace identifier:') {var ($cnt,@lin) = (0,last) loop $lin (@lin) {var $lin = field(':\s+',2,$lin) var $trc = catFile(value($lin)) if missing($lnk{$trc}) {incr $cnt output E,concat('trc',$cnt,'_',basename($trc,'.trc'),'.dat') call writeData($trc) var $lnk{$trc} = concat('[[',getRawLink(true),'][_blank][',$trc,']]') close } call setDataValue('trc',key($lin),$lnk{$trc},1) } loop $key (getDataKeys('trc')) call log( '|*',$key,'*|',join('%BR%',getDataKeys('trc',$key)),'|') } # Terminate the report and restart event logging if hasLog(true) call log($TOP) call log('---### ORADDC collection ended at ',${RDA.T_LOCALTIME}) } # Collect a 10046 trace macro collect_10046 {var ($pid) = @arg import $PID keep $PID job {import $pid,$PID call create_lock($PID,'ddcpt',getPid(),'pid=',$pid) call clone_log() call setSqlTarget($[tgt]) var $sql = check_wait('10046 trace (PID: ',$pid,')') append $sql {oradebug setospid :1 "PROMPT oradebug event 10046 trace name context forever, level 12 "oradebug event 10046 trace name context forever, level 12 "oradebug tracefile_name "oradebug setmypid } output E,concat('pt_',$pid,'.tmp') call writeSql(bindSql($sql,$pid)) if grepFile(getFile('/'),'\.trc','if') call log_event('Trace identifier: 10046 Trace=',trim(last)) } } # Collect an active session history dump macro collect_ashdump {import $CPG,$DBC,$DDC_ASH,$PID,$TOP keep $CPG,$DBC,$DDC_ASH,$PID,$TOP job {import $CPG,$DBC,$DDC_ASH,$PID,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) var $sql = check_wait('active session history') if $DBC {append $sql {alter session set tracefile_identifier='ashdump'; } } elsif $CPG {append $sql {oradebug call ksmcpg } } append $sql {oradebug setmypid "oradebug dump ashdump :1 "oradebug tracefile_name } output E,concat('dd.tmp') call writeSql(bindSql($sql,$DDC_ASH)) var $rpt = getFile('/') if grepFile($rpt,'\.trc','if') {var $fil = trim(last) call log_event('Trace identifier: ASH dump=',$fil) } # Define a macro to resolve events macro add_event {import $TOP # Determine the database version if grepBuffer('ASH','^Oracle Database \S+ ','fr') var ($ver) = match(last,'^Oracle Database (\S+)') else return # Create an internal table if match($ver,'^10') {if !and(grepBuffer('ASH','HEADER BEGIN>>>$','fir'),\ createTable('ash',chomp(getLine('ASH'))),\ grepBuffer('ASH','DUMP BEGIN>>>$','fir')) return call setTableType('ash','TSP','SAMPLE_TIME') while getLine('ASH') {var $lin = chomp(last) break match($lin,'DUMP END>>>$',true) call addTableRow('ash',$lin) } } else {# Define parsing macros macro add_ash_column {var (\$def,$lin) = @arg if !match($lin,'^[^\s,]+\s+CONSTANT\s',true) {if match($lin,'^([^\s,]+)') var $def = join(',',$def,last) } return -1 } macro create_ash_table {var ($def) = @arg call createTable('ash',$def) call setTableType('ash','TSP','SAMPLE_TIME','SQL_EXEC_START') } macro load_ash_row {var $row = join('',parseBuffer()) if length($row) call addTableRow('ash',$row) } macro merge_ash_row {var (\$row,$lin) = @arg var $row = concat($row,$lin) return -1 } # Define a parser call parseReset() call parseBegin('TOP','HEADER BEGIN>>>$','HDR') call parseEnd('HDR','HEADER END>>>$') call parseBegin('HDR','^\($','TBL') call parseEnd('TBL','^\)$') call parseInfo('TBL','end',create_ash_table($def)) call parseInfo('TBL','flp',false) call parseCode('TBL',add_ash_column(\$def,line)) call parseBegin('TOP','DUMP BEGIN>>>$','DAT') call parseBegin('DAT','^####$','REC','REC') call parseEnd('DAT','DUMP END>>>$') call parseInfo('REC','buf',-1) call parseInfo('REC','end',load_ash_row()) call parseInfo('REC','flp',false) # Parse the trace file var $def = undef call parse('ASH') if !$def return } # Modify the table var $off2 = getTableOffset('ash','BLOCKING_SESSION_SERIAL#') if defined($off2) {var $off1 = getTableOffset('ash','BLOCKING_SESSION') call addTableColumn('ash','BLOCKING_SESSION_ID_SERIAL',$off1,\ '%s-%s',$off1,$off2) } var $off = getTableOffset('ash','SESSION_ID') call addTableColumn('ash','SESSION_ID_SERIAL',$off,\ '%s-%s',$off,'SESSION_SERIAL#') call addTableColumn('ash','SNAP_ID','DBID',0) call addTableColumn('ash','WAIT_CLASS_ID','WAIT_TIME') call addTableColumn('ash','EVENT','EVENT_ID','') call addTableColumn('ash','P1TEXT','P1','') call addTableColumn('ash','P2TEXT','P2','') call addTableColumn('ash','P3TEXT','P3','') call addTableColumn('ash','WAIT_CLASS','WAIT_CLASS_ID','') call setTableType('ash','NUM',\ 'BLOCKING_SESSION','DBID','P1','P2','P3','TIME_WAITED','WAIT_TIME') loop $nam (getTableColumns('ash')) {if match($nam,'(_ID|_NUMBER|_VALUE|\#)$') call setTableType('ash','NUM',$nam) } # Add event description when applicable if getTableKeys('ash','EVENT_ID') {var $key = join(',',last) # Create a table for v$event_name var @col = ('EVENT_ID','EVENT','P1TEXT','P2TEXT','P3TEXT','WAIT_CLASS') call createTable('evt',@col) set $sql {SELECT 'EVT="' || " event_id || '","' || " name || '","' || " parameter1 || '","' || " parameter2 || '","' || " parameter3 || '","' || " wait_class || '"' " FROM v$event_name " WHERE event_id IN (:1); } loop $lin (grepSql(bindSql($sql,$key),'^EVT=.*')) call addTableRow('evt',value($lin)) call addTableUid('evt',0) # Merge the specified columns using the EVENT_ID call mergeTable('ash','evt','EVENT_ID',$col[1],1,\ $col[2],2,\ $col[3],3,\ $col[4],4,\ $col[5],5) } # Write the table contents to the report in the desired order output E,dd prefix write '---+!! Active Session History' call writeTable('ash',\ 'INSTANCE_NUMBER/A,SAMPLE_TIME/D,SESSION_ID/A,SESSION_SERIAL#/A') if hasOutput(true) {write $TOP call log_event('Spooling to: Active Session History=',\ basename(renderFile())) } # Delete the tables call deleteTable('ash') call deleteTable('evt') } # Add event information in the ASH records if and($DBC,$fil,createBuffer('ASH','R',$fil)) {call add_event() call deleteBuffer('ASH') } # Indicate the job completion call dsp_event('(active session history) Done.') call $lck->unlink } } # Collect an error stack macro collect_error_stack {var ($pid) = @arg import $DDC_SLP,$PID,@EVT keep $DDC_SLP,$PID,@EVT var $min = expr('*',3,$DDC_SLP) call dsp_event('Please wait, this will take at least ',$min,' seconds ...') job {import $pid,$DDC_SLP,$PID,@EVT var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) var $sql = check_wait('error stack (PID: ',$pid,')') append $sql {oradebug setospid :2 "oradebug unlimit "PROMPT oradebug dump errorstack 3 "oradebug dump errorstack 3 "PROMPT ___Macro_DspEvent(2)___ "!!sleep(:1) "oradebug dump errorstack 3 "PROMPT ___Macro_DspEvent(1)___ "!!sleep(:1) "oradebug dump errorstack 3 "oradebug tracefile_name "PROMPT ___Macro_DspEvent(0)___ } output E,concat('pe_',$pid,'.tmp') var @EVT = (\ concat('(PID: ',$pid,' / errorstack 3 of 3) Done.'),\ concat('(PID: ',$pid,' / errorstack 2 of 3) Sleeping for ',$DDC_SLP,\ ' seconds ...'),\ concat('(PID: ',$pid,' / errorstack 1 of 3) Sleeping for ',$DDC_SLP,\ ' seconds ...')) call writeSql(bindSql($sql,$DDC_SLP,$pid)) if grepFile(getFile('/'),'\.trc','if') call log_event('Trace identifier: Error Stack=',trim(last)) call $lck->unlink } } # Collect hang analyze information macro collect_hang_analyze {import $CPG,$DBC,$DDC_SLP,$HAL,$PID,@EVT keep $CPG,$DBC,$DDC_SLP,$HAL,$PID,@EVT var $min = expr('*',3,$DDC_SLP) call dsp_event('Please wait, this will take at least ',$min,' seconds ...') job {import $CPG,$DBC,$DDC_SLP,$HAL,$PID,@EVT var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) var $sql = check_wait('hang analyze') if $DBC {append $sql {alter session set tracefile_identifier='hanganalyze'; } } elsif $CPG {append $sql {oradebug call ksmcpg } } append $sql {oradebug setmypid "oradebug unlimit "PROMPT oradebug hanganalyze :2 "oradebug hanganalyze :2 "PROMPT ___Macro_DspEvent(2)___ "!!sleep(:1) "oradebug hanganalyze :2 "PROMPT ___Macro_DspEvent(1)___ "!!sleep(:1) "oradebug hanganalyze :2 "oradebug tracefile_name "PROMPT ___Macro_DspEvent(0)___ } output E,'da.tmp' var @EVT = (\ '(hang_analyze 3 of 3) Done.',\ concat('(hang_analyze 2 of 3) Sleeping for ',$DDC_SLP,' seconds ...'),\ concat('(hang_analyze 1 of 3) Sleeping for ',$DDC_SLP,' seconds ...')) call writeSql(bindSql($sql,$DDC_SLP,$HAL)) if grepFile(getFile('/'),'\.trc','i',-1) call log_event('Trace identifier: Hang Analyze=',trim(last)) call $lck->unlink } } # Collect a heapdump macro collect_heapdump {import $CPG,$DBC,$PID,@EVT keep $CPG,$DBC,$PID,@EVT job {import $CPG,$DBC,$PID,@EVT var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) var $sql = check_wait('heapdump') if $DBC {append $sql {alter session set tracefile_identifier='heapdump'; } } elsif $CPG {append $sql {oradebug call ksmcpg } } append $sql {oradebug setmypid "oradebug unlimit "PROMPT oradebug dump heapdump 536870915; "oradebug dump heapdump 536870915; "oradebug tracefile_name "PROMPT ___Macro_DspEvent(0)___ } output E,'dh.tmp' var @EVT = ('(heapdump 536870915) Done.') call writeSql($sql) if grepFile(getFile('/'),'\.trc','if') call log_event('Trace identifier: Heapdump=',trim(last)) call $lck->unlink } } # Collect the library cache macro collect_lib_cache {import $CPG,$DBC,$PID,@EVT keep $CPG,$DBC,$PID,@EVT job {import $CPG,$DBC,$PID,@EVT var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) var $sql = check_wait('library cache') if $DBC {append $sql {alter session set tracefile_identifier='libcache'; } } elsif $CPG {append $sql {oradebug call ksmcpg } } append $sql {oradebug setmypid "PROMPT oradebug dump library_cache 4 "oradebug dump library_cache 4 "oradebug tracefile_name "PROMPT ___Macro_DspEvent(0)___ } output E,'dl.tmp' var @EVT = ('(library cache) Done.') call writeSql($sql) if grepFile(getFile('/'),'\.trc','if') call log_event('Trace identifier: Library Cache=',trim(last)) call $lck->unlink } } # Collect a process state dump macro collect_process_state {var ($pid) = @arg import $DDC_SLP,$PID,@EVT keep $DDC_SLP,$PID,@EVT var $min = expr('*',3,$DDC_SLP) call dsp_event('Please wait, this will take at least ',$min,' seconds ...') job {import $pid,$DDC_SLP,$PID,@EVT var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) var $sql = check_wait('process state (PID: ',$pid,')') append $sql {oradebug setospid :2 "PROMPT oradebug dump processstate 10 "oradebug dump processstate 10 "PROMPT ___Macro_DspEvent(2)___ "!!sleep(:1) "oradebug dump processstate 10 "PROMPT ___Macro_DspEvent(1)___ "!!sleep(:1) "oradebug dump processstate 10 "oradebug tracefile_name "oradebug setmypid "PROMPT ___Macro_DspEvent(0)___ } output E,concat('pp_',$pid,'.tmp') var @EVT = (\ concat('(PID: ',$pid,' / process_state 3 of 3) Done.'),\ concat('(PID: ',$pid,' / process_state 2 of 3) Sleeping for ',$DDC_SLP,\ ' seconds ...'),\ concat('(PID: ',$pid,' / process_state 1 of 3) Sleeping for ',$DDC_SLP,\ ' seconds ...')) call writeSql(bindSql($sql,$DDC_SLP,$pid)) if grepFile(getFile('/'),'\.trc','if') call log_event('Trace identifier: Process State=',trim(last)) call $lck->unlink } } # Collect the row cache macro collect_row_cache {import $CPG,$DBC,$PID,@EVT keep $CPG,$DBC,$PID,@EVT job {import $CPG,$DBC,$PID,@EVT var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) var $sql = check_wait('row cache') if $DBC {append $sql {alter session set tracefile_identifier='rowcache'; } } elsif $CPG {append $sql {oradebug call ksmcpg } } append $sql {oradebug setmypid "PROMPT oradebug dump row_cache 10 "oradebug dump row_cache 10 "oradebug tracefile_name "PROMPT ___Macro_DspEvent(0)___ } output E,'dr.tmp' var @EVT = ('(row cache) Done.') call writeSql($sql) if grepFile(getFile('/'),'\.trc','if') call log_event('Trace identifier: Row Cache=',trim(last)) call $lck->unlink } } # Collect a system state dump macro collect_system_state {import $CPG,$DBC,$DDC_SLP,$PID,$SDL,@EVT keep $CPG,$DBC,$DDC_SLP,$PID,$SDL,@EVT var $min = expr('*',3,$DDC_SLP) call dsp_event('Please wait, this will take at least ',$min,' seconds ...') job {import $CPG,$DBC,$DDC_SLP,$PID,$SDL,@EVT var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) var $sql = check_wait('system state') if $DBC {append $sql {alter session set tracefile_identifier='systemstate'; } } elsif $CPG {append $sql {oradebug call ksmcpg } } append $sql {oradebug setmypid "oradebug unlimit "PROMPT oradebug dump systemstate :2 "oradebug dump systemstate :2 "PROMPT ___Macro_DspEvent(2)___ "!!sleep(:1) "oradebug dump systemstate :2 "PROMPT ___Macro_DspEvent(1)___ "!!sleep(:1) "oradebug dump systemstate :2 "oradebug tracefile_name "PROMPT ___Macro_DspEvent(0)___ } output E,'ds.tmp' var @EVT = (\ concat('(system_state 3 of 3) Done.'),\ concat('(system_state 2 of 3) Sleeping for ',$DDC_SLP,' seconds ...'),\ concat('(system_state 1 of 3) Sleeping for ',$DDC_SLP,' seconds ...')) call writeSql(bindSql($sql,$DDC_SLP,$SDL)) if grepFile(getFile('/'),'\.trc','if') call log_event('Trace identifier: System State=',trim(last)) call $lck->unlink } } # Get the process identifier of a background process macro get_background {var (\%pid,$sid,\%pat) = @arg if or(isWindows(),isCygwin(),isVms()) {# Outside Unix, use the database debug 'Loading the background process identifiers ...' set $sql {SELECT b.name || '=' || p.spid " FROM gv$process p,gv$bgprocess b " WHERE p.inst_id = b.inst_id " AND p.addr = b.paddr; } call loadSql($sql) loop $nam (keys(%pat)) {if grepLastSql(concat($pat{$nam},'='),'i') {loop $lin (last) var $pid{key($lin)} = value($lin) } else call dsp_event('WARNING: Unable to identify the "',$nam,'" process(es)') } } elsif loadCommand('ps -ef') {# Use the ps command for UNIX to get the process identifier loop $nam (keys(%pat)) {var $pat = concat('(',$pat{$nam},')_',replace($sid,'\+','\+',true),'\b') if grepLastFile($pat,'i') {loop $lin (last) {var ($key) = match($lin,$pat,true) var $pid{$key} = field('\s+',1,$lin) } } else call dsp_event('WARNING: Unable to identify the "',$nam,'" process(es)') } } } # Collect the session process identifiers for the blocking sessions macro get_blocking_pids {var $sql = check_wait('blocking sessions PIDs') append $sql {SELECT 'pid=' || p.spid " FROM v$process p,v$session s,dba_blockers b " WHERE p.addr = s.paddr " AND b.holding_session = s.sid; } var @tbl = () loop $lin (grepSql($sql,'^pid=')) call push(@tbl,value($lin)) return @tbl } # Collect the session process identifiers for the events specified macro get_event_pids {import $TOP if @arg {# Display relevant events call end_log() prefix $[log] {call log('---++ Requested Sessions on Following Wait Events') call log('|*Event#*|*Wait Event*|') } var $sql = check_wait('event PIDs') append $sql {SELECT '|' || " e.event# || '|' || " e.name || '|' " FROM v$event_name e " WHERE e.event# IN (:1); } call writeSql($[log],bindSql($sql,join(',',@arg))) if hasLog(true) call log($TOP) call begin_log() # Collect the 10 first session process identifiers for each event specified loop $evt (@arg) {var $sql = check_wait('10 first sessions for ',$evt,' event') append $sql {SELECT 'pid=' || p.spid " FROM v$process p, " v$session s, " v$session_wait w, " v$event_name e " WHERE p.addr = s.paddr " AND e.event# IN (:1) " AND w.sid = s.sid " AND e.name = w.event " AND ROWNUM < 11; } loop $lin (grepSql(bindSql($sql,$evt),'^pid=')) call push(@tbl,value($lin)) } } return @tbl } # Collect the event history information for the events specified macro get_event_hist {var ($DDC_EVT_SLP,@evt) = @arg import $PID,$TOC,$TOP,@EVT job {import $PID,$TOC,$TOP,@EVT var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) var $sql = check_wait('event histogram data') append $sql {SELECT '|' || " e.event# || '|' || " e.name || '|' " FROM v$event_name e " WHERE e.event# IN (:1); } if loadSql(bindSql($sql,join(',',@evt))) {var %evt = () loop $lin (grepLastSql('^\|\d')) {var (undef,$evt,$nam,undef) = split('\|',$lin,4) var $evt{$nam} = $evt } set $sql {SELECT wait_time_milli || ',' || " wait_count " FROM v$event_histogram " WHERE event# = :1 " ORDER BY wait_time_milli; } var @EVT = (\ '(snapshot of event histogram 2 of 2) Done.',\ concat('(snapshot of event histogram 1 of 2) Sleeping for ',$DDC_EVT_SLP,\ ' seconds ...')) call clearData() call createData('',createData('',list())) for $idx (1,2) {loop $nam (keys(%evt)) {loop $lin (grepSql(bindSql($sql,$evt{$nam}),'^\d*,')) {var ($tim,$cnt) = split(',',$lin,2) call addDataValue($nam,$tim,$cnt) if missingData($nam,$tim) call addDataValue($nam,$tim,0) } } if expr('<>',$idx,2) {call DspEvent(1) sleep $DDC_EVT_SLP } else call DspEvent(0) } output E,de loop $nam (keys(%evt)) {prefix {if !isCreated() {write '---+!! Snapshot Data from V$EVENT_HISTOGRAM' write $TOC } write "---+ '",$nam,"' Wait Event Histogram" write '| *Response Bucket (ms)*| *Event Count(1)*| *Event Count(2)*| \ *Delta*| *Weighted Total Time (ms)*|' } loop $bck (getDataIndex($nam)) {var ($cnt1,$cnt2) = getDataValue($nam,$bck) var $del = expr('-',$cnt2,$cnt1) var $tot = expr('*',$del,$bck) write '| ',join('| ',$bck,$cnt1,$cnt2,$del,$tot),'|' } if hasOutput(true) write $TOP } if isCreated(true) {var $rpt = renderFile() call log_event('Spooling to: Event Histogram=',basename($rpt)) } } close call $lck->unlink } } # Collect the process identifiers for the specified listener names macro get_listener_pids {var @lsn = @arg var ($osn,$PS_ARG,$PS_EF,$PS_ELF,@pid) = (getOsName()) # Get the ps command format if match($osn,'solaris') {run OS:OSsunos('PS') } elsif match($osn,'hpux') {run OS:OShpux('PS') } elsif match($osn,'aix') {run OS:OSaix('PS') } elsif match($osn,'dec_osf') {run OS:OSosf('PS') } elsif match($osn,'linux') {run OS:OSlinux('PS') } elsif match($osn,'dynixptx') {run OS:OSptx('PS') } elsif match($osn,'darwin') {run OS:OSdarwin('PS') } elsif isUnix() {run OS:OSunix('PS') } else return @pid # Identify the user-specified listener names macro chk_listener {var (\@pid,\@lsn,$fld1,$fld2,$off,@lin) = @arg loop $lin (@lin) {var $lsn = field('\s+',$fld1,substr($lin,$off)) next !grep(@lsn,concat('\b',verbatim($lsn),'\b'),'if') var $pid = field('\s+',$fld2,$lin) if match($pid,'^\d+$') call push(@pid,$pid) } } # Extract the listener list if loadCommand(replace($PS_ARG,'comm,args','pid,comm,args')) call chk_listener(\@pid,\@lsn,3,0,0,grepLastFile('tnslsnr')) elsif match($osn,'linux') {if grepDir('/etc','suse.*release','i') var $off = 6 else var $off = 7 call chk_listener(\@pid,\@lsn,$off,3,39,\ grepCommand($PS_ELF,'tnslsnr.*inherit')) } elsif match($osn,'aix') call chk_listener(\@pid,\@lsn,3,1,39,grepCommand($PS_EF,'tnslsnr')) else call chk_listener(\@pid,\@lsn,2,1,42,grepCommand($PS_EF,'tnslsnr')) # Get the listener PID's return @pid } # Collect the session process identifiers for the Oracle process specified macro get_oracle_pids {var $sql = check_wait('Oracle PIDs') append $sql {SELECT 'pid=' || p.spid " FROM v$process p " WHERE p.pid IN (:1); } loop $lin (grepSql(bindSql($sql,join(',',@arg)),'^pid=')) call push(@tbl,value($lin)) return @tbl } # Collect the session process identifiers for the session identifiers specified macro get_session_pids {var $sql = check_wait('Session PIDs') append $sql {SELECT 'pid=' || p.spid " FROM v$process p,v$session s " WHERE p.addr = s.paddr " AND s.sid IN (:1); } loop $lin (grepSql(bindSql($sql,join(',',@arg)),'^pid=')) call push(@tbl,value($lin)) return @tbl } # Collect the session process identifiers for the user specified macro get_user_pids {var $sql = check_wait('User PIDs') append $sql {SELECT 'pid=' || p.spid " FROM v$process p,v$session s " WHERE p.addr = s.paddr " AND s.username = UPPER(':1'); } loop $lin (grepSql(bindSql($sql,@arg),'^pid=')) call push(@tbl,value($lin)) return @tbl } # Report shared pool chunks macro report_chunks {import $PID,$TTL,@HDR,@TTL job {import $PID,$TTL,@HDR,@TTL var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) output E,dh var $TTL = '---++ Shared Pool Memory Utilisation' var @TTL = ('',\ '---+++ Database Instance',\ '---+++ Shared Pool Chunk Allocation (Size Aggregations)',\ '---+++ Shared Pool Chunk Allocation (Detailed)') var @HDR = ('',\ '|*DBname*|*Instance*|*Date/Time*|',\ '| *SubPool*|*Size*|*Status*| *Min Bytes*| *Avg Bytes*| \ *Max Bytes*| *Tot Bytes*| *Count*|',\ '| *SubPool*|*Chunk Comment*|*Size*| *Count*|*Status*| *Bytes*|') var $sql = check_wait('shared pool chunks') append $sql {SELECT '|' || " name || '|' || " instance_name || '|' || " TO_CHAR(SYSDATE,'DD-Mon-YYYY HH24:MI:SS') || '|' " FROM v$instance,v$database; "PROMPT ___Macro_separator(2)___ "SELECT '| ' || " ksmchidx || '|' || " DECODE(ROUND(ksmchsiz/1000),0,'0-1K', " 1,'1-2K', " 2,'2-3K', " 3,'3-4K', " 4,'4-5K', " 5,'5-6k', " 6,'6-7k', " 7,'7-8k', " 8,'8-9k', " 9,'9-10k', " '> 10K') || '|' || " ksmchcls || '| ' || " MIN(ksmchsiz) || '| ' || " ROUND(AVG(ksmchsiz)) || '| ' || " MAX(ksmchsiz) || '| ' || " SUM(ksmchsiz) || '| ' || " COUNT(*) || '|' " FROM x$ksmsp " GROUP BY ksmchidx,ksmchcls,ksmchcls, " DECODE(ROUND(ksmchsiz/1000),0,'0-1K', " 1,'1-2K', " 2,'2-3K', " 3,'3-4K', " 4,'4-5K', " 5,'5-6k', " 6,'6-7k', " 7,'7-8k', " 8,'8-9k', " 9,'9-10k', " '> 10K') " ORDER BY ksmchidx,ksmchcls; "PROMPT ___Macro_separator(3)___ "SELECT '| ' || " ksmchidx || '|' || " ksmchcom || '|' || " DECODE(ROUND(ksmchsiz/1000),0,'0-1K', " 1,'1-2K', " 2,'2-3K', " 3,'3-4K', " 4,'4-5K', " 5,'5-6k', " 6,'6-7k', " 7,'7-8k', " 8,'8-9k', " 9,'9-10k', " '> 10K') || '| ' || " COUNT(*) || '|' || " ksmchcls || '| ' || " SUM(ksmchsiz) || '|' " FROM x$ksmsp " GROUP BY ksmchidx, " ROUND(ksmchsiz/1000), " ksmchcls, " 'sga heap(' || ksmchidx || ',0)', " ksmchcom, " ksmchcls, " DECODE(ROUND(ksmchsiz/1000),0,'0-1K', " 1,'1-2K', " 2,'2-3K', " 3,'3-4K', " 4,'4-5K', " 5,'5-6k', " 6,'6-7k', " 7,'7-8k', " 8,'8-9k', " 9,'9-10k', " '> 10K') " ORDER BY ksmchidx; } call separator(1) call writeSql($sql) call separator(0) if isCreated(true) {var $rpt = renderFile() call dsp_event('(shared spool chunks) Done.') call log_event('Spooling to: Shared Pool Chunks=',basename($rpt)) } call $lck->unlink } } # Report locking contention macro report_locking_contention {import $PID,$TTL,@HDR,@TTL job {import $PID,$TTL,@HDR,@TTL var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) output E,dc var $TTL = '---++!! Locking Contention Report' var @TTL = ('',\ '---+++ Database Instance',\ '---+++ Lock Tree',\ '---+++ Lock / Block Objects',\ '---+++ Lock / Block Processes',\ '---+++ Lock / Block Transactions') var @HDR = ('',\ '|*DBname*|*Instance*|*Date/Time*|',\ '|*Instance-SID*|*Username*|*Lock%BR%Type*|*Mode%BR%Held*|\ *Mode%BR%Requested*|*ID1-ID2*|',\ '|*Instance-SID*|*Object*|*Lock Wait*|*ID1-ID2*|*SQL Text*|',\ '|*Instance*|*Oracle%BR%User*| *Oracle%BR%PID*|\ *Session%BR%Module*| *SID*|*SERIAL#*|*OSUser*| *O/S%BR%PID*| \ *O/S%BR%PPID*|*Lockwait*|*ID1-ID2*|',\ '|*Instance-SID*|*Username*|*Table Name*|*Mode%BR%Held*|\ *Mode%BR%Requested*|*ID1-ID2*|*Lock%BR%Type*|') var $sql = check_wait('locking contention') append $sql {SELECT '|' || " name || '|' || " instance_name || '|' || " TO_CHAR(SYSDATE,'DD-Mon-YYYY HH24:MI:SS') || '|' " FROM v$instance,v$database; "PROMPT ___Macro_separator(2)___ "SELECT '|' || " REPLACE(LPAD(' ',3*(LEVEL-1)),' ',' ') || wait_id || '|' || " wusername || '|' || " lock_type || '|' || " mode_held || '|' || " mode_requested || '|' || " DECODE(lock_id1,NULL,NULL,lock_id1 || '-' || lock_id2) || '|' " FROM (SELECT sw.inst_id || '-' || sw.sid wait_id, " sh.inst_id || '-' || sh.sid hold_id, " lh.type lock_type, " DECODE(sh.command,0,'None', " DECODE(lh.lmode, " 0,'None', /* Mon Lock equivalent */ " 1,'Null', /* N */ " 2,'Row-S (SS)', /* L */ " 3,'Row-X (SX)', /* R */ " 4,'Share', /* S */ " 5,'S/Row-X (SSX)', /* C */ " 6,'Exclusive', /* X */ " TO_CHAR(lh.lmode))) mode_held, " DECODE(lw.request, " 0,'None', /* Mon Lock equivalent */ " 1,'Null', /* N */ " 2,'Row-S (SS)', /* L */ " 3,'Row-X (SX)', /* R */ " 4,'Share', /* S */ " 5,'S/Row-X (SSX)', /* C */ " 6,'Exclusive', /* X */ " TO_CHAR(lw.request)) mode_requested, " lw.id1 lock_id1, " lw.id2 lock_id2, " NVL(sw.username,'Internal') wusername, " NVL(sh.username,'Internal') husername " FROM gv$lock lh,gv$lock lw,gv$session sh,gv$session sw " WHERE lh.sid = sh.sid " AND lw.sid = sw.sid " AND sh.type != 'BACKGROUND' " AND sw.type != 'BACKGROUND' " AND lh.lmode != 0 " AND lw.lmode = 0 " AND lw.id1 = lh.id1 " AND lw.id2 = lh.id2 " UNION " (SELECT hold_id, " NULL, " NULL, " NULL, " NULL, " NULL, " NULL, " NULL, " NULL " FROM (SELECT sh.inst_id || '-' || sh.sid hold_id, " NULL wait_id, " NULL lock_type, " NULL mode_held, " NULL mode_requested, " NULL lock_id1, " NULL lock_id2, " NULL wusername, " NULL husername " FROM gv$lock lh,gv$lock lw,gv$session sh,gv$session sw " WHERE lh.sid = sh.sid " AND lw.sid = sw.sid " AND sh.type != 'BACKGROUND' " AND sw.type != 'BACKGROUND' " AND lh.lmode != 0 " AND lw.lmode = 0 " AND lw.id1 = lh.id1 " AND lw.id2 = lh.id2) " MINUS " SELECT wait_id, " NULL, " NULL, " NULL, " NULL, " NULL, " NULL, " NULL, " NULL " FROM (SELECT sw.inst_id || '-' || sw.sid wait_id, " NULL hold_id, " NULL lock_type, " NULL mode_held, " NULL mode_requested, " NULL lock_id1, " NULL lock_id2, " NULL wusername, " NULL husername " FROM gv$lock lh,gv$lock lw,gv$session sh,gv$session sw " WHERE lh.sid = sh.sid " AND lw.sid = sw.sid " AND sh.type != 'BACKGROUND' " AND sw.type != 'BACKGROUND' " AND lh.lmode != 0 " AND lw.lmode = 0 " AND lw.id1 = lh.id1 " AND lw.id2 = lh.id2) " ) " ) " CONNECT BY PRIOR wait_id = hold_id " START WITH hold_id IS NULL; "PROMPT ___Macro_separator(3)___ "SELECT '|'|| " inst_sid || ' |' || " object || ' |' || " lock_wait || ' |' || " id || ' |' || " REPLACE(REPLACE(REPLACE(sql_text, " '|', '|'), " '<', '<'), " '>', '>') || ' |' "FROM (SELECT b.inst_id || '-' || b.sid inst_sid, " c.owner || '.' || c.object object, " b.lockwait lock_wait, " d.id1 || '-' || d.id2 id, " a.sql_text sql_text " FROM gv$sqltext a,gv$session b,gv$access c, " (SELECT a.inst_id,a.sid,a.id1,a.id2 " FROM gv$lock a " WHERE EXISTS (SELECT NULL " FROM gv$lock b " WHERE b.id1=a.id1 " AND b.id2=a.id2 " AND b.request > 0)) d " WHERE a.address = b.sql_address " AND a.inst_id = b.inst_id " AND b.inst_id = c.inst_id " AND c.inst_id = d.inst_id " AND a.hash_value = b.sql_hash_value " AND b.sid = c.sid " AND c.sid = d.sid " AND c.owner != 'SYS' " UNION " SELECT b.inst_id || '-' || b.sid inst_id, " c.owner || '.' || c.object object, " '' lock_wait, " d.id1 || '-' || d.id2 id, " a.sql_text sql_text " FROM gv$sqltext a,gv$session b,gv$access c, " (SELECT a.inst_id,a.sid,a.id1,a.id2 " FROM gv$lock a " WHERE (id1,id2) IN (SELECT b.id1,b.id2 " FROM gv$lock b " WHERE b.id1 = a.id1 " AND b.id2 = a.id2 " AND b.request > 0)) d " WHERE a.address = b.prev_sql_addr " AND b.sql_address = '00' " AND a.inst_id = b.inst_id " AND b.inst_id = c.inst_id " AND c.inst_id = d.inst_id " AND b.sid = c.sid " AND c.sid = d.sid " AND a.hash_value = b.prev_hash_value " AND c.owner != 'SYS') " ORDER BY id,lock_wait desc,inst_sid; "PROMPT ___Macro_separator(4)___ "SELECT '|' || " s.inst_id || ' |' || " SUBSTR(s.username,1,11) || ' | ' || " p.pid || '|' || " s.module || ' |' || " s.sid || ' |' || " s.serial# || ' |' || " osuser || ' | ' || " p.spid || '| ' || " s.process || '|' || " NVL(s.lockwait,'') || ' |' || " l.id1 || '-' || l.id2 || ' |' " FROM gv$process p,gv$session s, " (SELECT a.inst_id,a.sid,a.id1,a.id2 " FROM gv$lock a " WHERE EXISTS (SELECT NULL " FROM gv$lock b " WHERE b.id1 = a.id1 " AND b.id2 = a.id2 " AND b.request > 0)) l " WHERE p.inst_id = s.inst_id " AND s.inst_id = l.inst_id " AND l.sid = s.sid " AND p.addr = s.paddr " ORDER BY l.id1,l.id2,s.lockwait desc,s.inst_id,s.sid; "PROMPT ___Macro_separator(5)___ "SELECT '|' || " s.inst_id || '-' || s.sid || '|' || " NVL(s.username,'Internal') || '|' || " DECODE(command,0,'None', " DECODE(l.id2,0,u1.name || '.' || SUBSTR(t1.name,1,20), " 'Rollback Segment')) || '|' || " DECODE(l.lmode, " 0,'None', /* Mon Lock equivalent */ " 1,'Null', /* N */ " 2,'Row-S (SS)', /* L */ " 3,'Row-X (SX)', /* R */ " 4,'Share', /* S */ " 5,'S/Row-X (SSX)', /* C */ " 6,'Exclusive', /* X */ " TO_CHAR(l.lmode)) || '|' || " DECODE(l.request, " 0,'None', /* Mon Lock equivalent */ " 1,'Null', /* N */ " 2,'Row-S (SS)', /* L */ " 3,'Row-X (SX)', /* R */ " 4,'Share', /* S */ " 5,'S/Row-X (SSX)', /* C */ " 6,'Exclusive', /* X */ " TO_CHAR(l.request)) || '|' || " l.id1||'-'||l.id2 || '|' || " l.type || '|' " FROM gv$lock l,gv$session s,sys.user$ u1,sys.obj$ t1 " WHERE l.sid = s.sid and " t1.obj# = DECODE(l.id2,0,l.id1,1) and " u1.user# = t1.owner# and " s.type != 'BACKGROUND'and " (l.sid) IN (SELECT b.sid " FROM gv$lock b " WHERE b.request > 0) " ORDER BY l.id1,l.id2,l.request; } call separator(1) call writeSql($sql) call separator(0) if isCreated(true) {var $rpt = renderFile() call dsp_event('(locking contention) Done.') call log_event('Spooling to: Locking Contention=',basename($rpt)) } call $lck->unlink } } # Report session wait events macro report_session_events {import $PID,$TTL,@HDR,@TTL job {import $PID,$TTL,@HDR,@TTL var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) output E,dw var $TTL = '---++ Session Wait Events Report' var @TTL = ('',\ '---+++ Database Instance',\ '---+++ SMON Waits',\ '---+++ All Waits') var @HDR = ('',\ '|*DBname*|*Instance*|*Date/Time*|',\ '|*Program*|*Sid*|*Event*|*Total_Waits*|*Total_Timeouts*|\ *Average_Wait*|',\ '|*Program*|*Sid*|*Event*|*Total_Waits*|*Total_Timeouts*|\ *Average_Wait*|') var $sql = check_wait('session wait events') append $sql {SELECT '|' || " name || '|' || " instance_name || '|' || " TO_CHAR(SYSDATE,'DD-Mon-YYYY HH24:MI:SS') || '|' " FROM v$instance,v$database; "PROMPT ___Macro_separator(2)___ "SELECT '|' || " p.program || '|' || " se.sid || '|' || " se.event || '| ' || " se.total_waits || '| ' || " se.total_timeouts || '| ' || " se.average_wait || '| ' " FROM v$session_event se,v$process p,v$session s " WHERE s.paddr = p.addr and " s.sid = se.sid and " se.average_wait > 0 and " p.program like '%(SMON)' " ORDER BY se.total_waits; "PROMPT ___Macro_separator(3)___ "SELECT '|' || " p.program || '|' || " se.sid || '|' || " se.event || '| ' || " se.total_waits || '| ' || " se.total_timeouts || '| ' || " se.average_wait || '|' " FROM v$session_event se,v$process p,v$session s " WHERE s.paddr = p.addr and " s.sid = se.sid and " se.average_wait > 0 " ORDER BY se.total_waits; } call separator(1) call writeSql($sql) call separator(0) if isCreated(true) {var $rpt = renderFile() call dsp_event('(session wait events) Done.') call log_event('Spooling to: Sessions Wait Events=',basename($rpt)) } call $lck->unlink } } # Deal with the dumps/traces associated with the background processes macro service_background {var ($nam,$pid) = @arg import $LDD_CMD,$PID,$PFL_CMD,$PFL_DIR,$PRE,$STK_CMD,$TOC,$TOP import $DDC_SLP,$TRC_CMD,$TRC_PGM,%DDC_PRC,$WAIT call dsp_event('"',$nam,'" process id: ',$pid) # Request a 10046 trace if exists($DDC_PRC{'T'}) {call dsp_event('Requesting a 10046, level 12 trace for ',$nam,' (PID: ',\ $pid,')') call collect_10046($pid) } # Request an error stack if exists($DDC_PRC{'E'}) {call dsp_event('Requesting an error stack for ',$nam,' (PID: ',$pid,')') call collect_error_stack($pid) } # Request a process state dump if exists($DDC_PRC{'P'}) {call dsp_event('Requesting a process state dump for ',$nam,' (PID: ',$pid,')') call collect_process_state($pid) } # Launch an operating system trace if exists($DDC_PRC{'O'}) {var $fil = catFile(${OUT.E},concat($PRE,'po_',$nam,'.trc')) var $cmd = concat($TRC_CMD,' -o ',$fil,' -p ',$pid) if $WAIT {call log_event('O/S trace written to: ',basename($fil)) job {import $cmd,$nam,$pid,$PID call kip(get_wait($nam,' trace (PID: ',$pid,') ...')) call clone_log() call dsp_event('Command: ',$cmd) output | $cmd call create_lock($PID,'ddcpo',getOutputPid()) } } else {call log_event('Tracing with ',$TRC_PGM) call log_event('O/S trace written to: ',basename($fil)) call dsp_event('Command: ',$cmd) job {import $cmd,$PID output | $cmd call create_lock($PID,'ddcpo',getOutputPid()) } } } # Request a process open files trace if exists($DDC_PRC{'F'}) {if $PFL_CMD var ($flg,$cmd) = (true,concat($PFL_CMD,' ',$pid)) else var ($flg,$dir) = (false,sprintf($PFL_DIR,$pid)) if $WAIT {job {import $cmd,$dir,$flg,$nam,$pid,$PID,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call kip(get_wait($nam,' pfiles trace')) call dsp_event($nam,' pfiles trace (PID: ',$pid,') ...') output E,concat('pf_',$nam,'.txt') if $flg {write '---+ Pfiles Trace for PID ',$pid call writeCommand($cmd) } else {write '---+ List of Open Files from ',$dir call statDir('n',$dir) call writeCommand($cmd) } write $TOP var $rpt = basename(renderFile()) call dsp_event($nam,' pfiles trace (PID: ',$pid,') completed') call log_event('Pfiles trace written to: ',$rpt) call $lck->unlink } } else {call dsp_event('Writing ',$nam,' process open files ...') job {import $cmd,$dir,$flg,$nam,$pid,$PID,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call dsp_event($nam,' pfiles trace (PID: ',$pid,') - please wait ...') output E,concat('pf_',$nam,'.txt') if $flg {write '---+ Pfiles Trace for PID ',$pid call writeCommand($cmd) } else {write '---+ List of Open Files from ',$dir call statDir('n',$dir) call writeCommand($cmd) } write $TOP var $rpt = basename(renderFile()) call dsp_event($nam,' pfiles trace (PID: ',$pid,') completed') call log_event('Pfiles trace written to: ',$rpt) call $lck->unlink } } } # Request a process dynamic libraries trace if exists($DDC_PRC{'L'}) {var $cmd = concat($LDD_CMD,' ',$pid) if $WAIT {job {import $cmd,$nam,$pid,$PID,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call kip(get_wait($nam,' pldd trace')) call dsp_event($nam,' pldd trace (PID: ',$pid,') ...') output E,concat('pl_',$nam,'.txt') write '---+ Pldd Trace for PID ',$pid call writeCommand($cmd) write $TOP var $rpt = basename(renderFile()) call dsp_event($nam,' pldd trace (PID: ',$pid,') completed') call log_event('Pldd trace written to: ',$rpt) call $lck->unlink } } else {call dsp_event('Writing ',$nam,' process dynamic libraries ...') job {import $cmd,$nam,$pid,$PID,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call dsp_event($nam,' pldd trace (PID: ',$pid,') - please wait ...') output E,concat('pl_',$nam,'.txt') write '---+ Pldd Trace for PID ',$pid call writeCommand($cmd) write $TOP var $rpt = basename(renderFile()) call dsp_event($nam,' pldd trace (PID: ',$pid,') completed') call log_event('Pldd trace written to: ',$rpt) call $lck->unlink } } } # Collect a stack trace if exists($DDC_PRC{'S'}) {var $cmd = concat($STK_CMD,' ',$pid) if $WAIT {job {import $cmd,$nam,$pid,$PID,$TOC,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call kip(get_wait($nam,' stack trace')) call dsp_event($nam,' stack trace (PID: ',$pid,\ ') - please wait (approx 6 minutes) ...') output E,concat('ps_',$nam,'.txt') write '---+!! Stack Trace for PID ',$pid write $TOC var $txt = ' (sleep 12)' for $cnt (1,11) {write '---+ Stack Trace No ',$cnt,$txt call writeCommand($cmd) write $TOP sleep 12 } for $cnt (12,24) {write '---+ Stack Trace No ',$cnt,$txt call writeCommand($cmd) write $TOP var $txt = ' (no sleep)' } var $rpt = basename(renderFile()) call dsp_event($nam,' stack trace (PID: ',$pid,') completed') call log_event('Stack trace written to: ',$rpt) call $lck->unlink } } else {call dsp_event('Writing ',$nam,' process stack (approx 6 minutes) ...') job {import $cmd,$nam,$pid,$PID,$TOC,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() sleep 1 call dsp_event($nam,' stack trace (PID: ',$pid,') - please wait ...') output E,concat('ps_',$nam,'.txt') write '---+!! Stack Trace for PID ',$pid write $TOC var $txt = ' (sleep 12)' for $cnt (1,11) {write '---+ Stack Trace No ',$cnt,$txt call writeCommand($cmd) write $TOP sleep 12 } for $cnt (12,24) {write '---+ Stack Trace No ',$cnt,$txt call writeCommand($cmd) write $TOP var $txt = ' (no sleep)' } var $rpt = basename(renderFile()) call dsp_event($nam,' stack trace (PID: ',$pid,') completed') call log_event('Stack trace written to: ',$rpt) call $lck->unlink } } } } # Wait for background task completion macro wait_exit {import $DDC_TRC_SLP,$PID,$TRC_PGM,%DDC_PRC if get_wait('all subprocesses') call kip(last) call dsp_event('Waiting for background processing to complete ...') # Wait for trace completion sleep 5 while grep_lock($PID,'ddcps') sleep 5 # Stop operating system traces if exists($DDC_PRC{'O'}) {var $pat = get_lock($PID,'ddcpo') if grep_lock($PID,'ddcpo') {var @lck = last call dsp_event('Terminating ',$TRC_PGM,' process(es) in ',$DDC_TRC_SLP,\ ' seconds ...') sleep $DDC_TRC_SLP loop $lck (@lck) {var ($flg,$pid) = match($lck,$pat,true) if ?$flg var $pid = concat('-',$pid) call dsp_event('Issuing: kill -9 ',$pid) call kill(9,$pid) } call delete_group($PID,'ddcpo') } } # Disable 10046 traces var @pid = () loop $lck (grep_lock($PID,'ddcpt')) call push(@pid,value(grepFile(catDir(${OUT.E},$lck),'pid=','f'))) if @pid {call dsp_event("The 10046 level 12 traces are still active for:\012 ",\ join(',',@pid)) if missing($DDC_PRC{'O'}) {call dsp_event('The 10046 traces will be switch off in approx. ',\ $DDC_TRC_SLP,' seconds') sleep $DDC_TRC_SLP } call dsp_event('The 10046 traces will now be switch off.') set $sql {oradebug setospid :1 "oradebug event 10046 trace name context off } loop $pid (@pid) {call dsp_event('Disabling 10046 trace (PID: ',$pid,') ...') call loadSql(bindSql($sql,$pid)) } call delete_group($PID,'ddcpt') } } # --- Main Section ----------------------------------------------------------- # Test the database connection debug 'Testing the database connection ...' call begin_log() if !$DBC {call dsp_event('Prelim mode set') var ($DBVER) = ('10') delete $DDC_DMP{'C'} delete $DDC_DMP{'W'} } elsif testSql() {call dsp_event('ERROR: Cannot connect to the database') var ($DBVER,%DDC_DMP) = ('') delete $DDC_PRC{'E'} delete $DDC_PRC{'T'} delete $DDC_PRC{'P'} } else var $DBVER = get_db_version(false,'10') # Set dump levels var $HAL = ${SET.DB.RACD.N_HANGANALYZE} var $SDL = ${SET.DB.RACD.N_SYSTEMSTATE} if !match($HAL,'^\d+$') var $HAL = cond(isWindows(),1,isCygwin(),1,3) if !match($SDL,'^\d+$') {var $ver = get_db_full_version() if or(isWindows(),isCygwin()) {if compare('VALID',$ver,'11.2.0.3') var $SDL = 11 elsif compare('VALID',$ver,'11.1') var $SDL = 2 elsif match($DBVER,'^10') var $SDL = 11 else var $SDL = 10 } elsif compare('VALID',$ver,'11.2.0.3') var $SDL = 266 elsif compare('VALID',$ver,'11.1') var $SDL = 258 elsif match($DBVER,'^10') var $SDL = 266 else var $SDL = 10 } # Disable the timeout call setSqlTimeout(0) # Give an overview call end_log() call log('---+ Report Overview') call log('|*Machine and Version*|',uname('a'),'|') if and($DBC,$DBVER) {var %ver = ('90','9i','92','9iR2',\ '10','10g assumed','101','10gR1','102','10gR2',\ '11','11g','111','11gR1','112','11gR2',\ '12','12c','121','12cR1','122','12cR2') call log('|*Database Version*|',nvl($ver{$DBVER},$DBVER),' |') } call log('|*ORACLE_SID*|',$ORACLE_SID,'|') call log('|*ORACLE_HOME*|',$ORACLE_HOME,'|') call log('|*ORADDC Options*|',\ cond(isFiltered(),replace($DDC_CMD,':',':',true),$DDC_CMD),' |') call log($TOP) call log('---+ Collection Details') call begin_log() # Find a pfiles program if exists($DDC_PRC{'F'}) {debug 'Searching for a pfiles command ...' if ?findCommand('procfiles') var ($PFL_PGM,$PFL_CMD,$PFL_DIR) = ('procfiles',concat(last,' -F')) elsif ?findCommand('pfiles') {var ($PFL_PGM,$PFL_CMD,$PFL_DIR) = ('pfiles',last) if match(getOsName(),'solaris') var $PFL_CMD = concat($PFL_CMD,' -F') } elsif ?testFile('x','/usr/proc/bin/pfiles') var ($PFL_PGM,$PFL_CMD,$PFL_DIR) = ('pfiles','/usr/proc/bin/pfiles') elsif ?testDir('r','/proc') var ($PFL_PGM,$PFL_DIR,$PFL_CMD) = ('proc_fd','/proc/%s/fd') else {var ($PFL_PGM,$PFL_CMD,$PFL_DIR) = () call dsp_event('WARNING: No pfiles command could be located.') call log_event('WARNING: ORADDC will skip open files requests.') delete $DDC_PRC{'F'} } if $PFL_CMD call log('Pfiles command: ',$PFL_CMD) } # Find a pldd program if exists($DDC_PRC{'L'}) {debug 'Searching for a pldd command ...' if ?findCommand('procldd') var ($LDD_PGM,$LDD_CMD) = ('procldd',concat(last,' -F')) elsif ?findCommand('pldd') {var ($LDD_PGM,$LDD_CMD) = ('pldd',last) if match(getOsName(),'solaris') var $LDD_CMD = concat($LDD_CMD,' -F') } elsif ?testFile('x','/usr/proc/bin/pldd') var ($LDD_PGM,$LDD_CMD) = ('pfiles','/usr/proc/bin/pldd') else {var ($LDD_PGM,$LDD_CMD) = () call dsp_event('WARNING: No pldd command could be located.') call log_event('WARNING: ORADDC will skip dynamic libraries requests.') delete $DDC_PRC{'L'} } if $LDD_CMD call log('Pldd command: ',$LDD_CMD) } # Find a trace program if exists($DDC_PRC{'O'}) {debug 'Searching for a trace command ...' if ?findCommand('truss') var ($TRC_PGM,$TRC_CMD) = ('truss',concat(last,' -f -a -i -e')) elsif ?findCommand('strace') {var ($TRC_PGM,$TRC_CMD) = ('strace',concat(last,' -f')) if !isWindows() var $TRC_CMD = concat($TRC_CMD,' -F') } elsif ?findCommand('tusc') var ($TRC_PGM,$TRC_CMD) = ('tusc',concat(last,' -f -a -i -e')) else {var ($TRC_PGM,$TRC_CMD) = () call dsp_event('WARNING: No trace command could be located.') call log_event('WARNING: ORADDC will skip operating system traces.') delete $DDC_PRC{'O'} } if $TRC_CMD call log('Trace command: ',$TRC_CMD) } # Find the pstack program if exists($DDC_PRC{'S'}) {debug 'Searching for the pstack command ...' if ?findCommand('procstack') var ($STK_PGM,$STK_CMD) = ('procstack',concat(last,' -F')) elsif ?findCommand('pstack') {var ($STK_PGM,$STK_CMD) = ('pstack',last) if match(getOsName(),'solaris') var $STK_CMD = concat($STK_CMD,' -F') } elsif ?testFile('x','/usr/proc/bin/pstack') var ($STK_PGM,$STK_CMD) = ('pstack','/usr/proc/bin/pstack') else {var ($STK_PGM,$STK_CMD) = () call dsp_event('WARNING: No pstack command could be located.') call log_event('WARNING: ORADDC will skip stack trace requests.') delete $DDC_PRC{'S'} } if $STK_CMD call log('Pstack command: ',$STK_CMD) } # Put a notice for the wait mode if $WAIT {debug debug 'NOTE: You have specified the wait option. Use the wake-up command' debug 'to start diagnostic collections for the waiting sessions.' debug } # Get background process identifiers if %DDC_BGP {var %pid = () call get_background(\%pid,$ORACLE_SID,\%DDC_BGP) loop $nam (keys(%pid)) {if $pid{$nam} call service_background($nam,last) } } # Request a ashdump if exists($DDC_DMP{'D'}) {call dsp_event('Requesting a active session history report ...') call collect_ashdump() } # Request a heapdump if exists($DDC_DMP{'H'}) {call dsp_event('Requesting a heapdump ...') call collect_heapdump() if $DBC {call dsp_event('Requesting a shared pool chunks report ...') call report_chunks() } } # Request a library cache dump if exists($DDC_DMP{'L'}) {call dsp_event('Requesting a library cache dump ...') call collect_lib_cache() } # Request a locking contention report if exists($DDC_DMP{'C'}) {call dsp_event('Requesting a locking contention report ...') call report_locking_contention() } # Request a row cache dump if exists($DDC_DMP{'R'}) {call dsp_event('Requesting a row cache dump ...') call collect_row_cache() } # Request an event histogram snapshot if exists($DDC_DMP{'E'}) {if and(compare('eq',$DDC_PID,'E'),@DDC_PID) {call dsp_event('Requesting a event histogram snapshot ...') call get_event_hist($DDC_EVT_SLP,@DDC_PID) } } # Request a session wait events report if exists($DDC_DMP{'W'}) {call dsp_event('Requesting a session wait events report ...') call report_session_events() } # Request a hang analyze dump if exists($DDC_DMP{'A'}) {call dsp_event('Requesting a hang analyze dump ...') call collect_hang_analyze() } # Request a system state sump if exists($DDC_DMP{'S'}) {call dsp_event('Requesting a system state dump ...') call collect_system_state() } # Get the process identifiers to analyze if and($WAIT,compare('ne',$DDC_PID,'-')) {debug debug 'WARNING: The -W option has been specified. If this was specified due to' debug 'issues with making new connections then tracing analysis of specified' debug 'sessions may fail!' debug } if compare('eq',$DDC_PID,'B') {# Get the PIDs of blocking sessions var @pid = get_blocking_pids() if @pid call dsp_event("Client PIDs [Blocking PIDs]:\012 ",join(',',@pid)) else {call dsp_event('WARNING: No Oracle blocking sessions detected') call wait_exit() } } elsif compare('eq',$DDC_PID,'E') {# Get the PIDs of sessions waiting on the wait#'s specified var @pid = get_event_pids(@DDC_PID) call dsp_event("Client PIDs [Waiting on event# ",join(',',@DDC_PID),\ "]:\012 ",join(',',@pid)) } elsif compare('eq',$DDC_PID,'L') {# Get the PIDs of listeners as specified by listener names var @pid = get_listener_pids(@DDC_PID) if @pid call dsp_event("Client PIDs [For listeners ",join(',',@DDC_PID),"]:\012 ",\ join(',',@pid)) } elsif compare('eq',$DDC_PID,'O') {# Get the PIDs of sessions connected as specified by Oracle PIDs var @pid = get_oracle_pids(@DDC_PID) if @pid call dsp_event("Client PIDs [-o ",join(',',@DDC_PID),"]:\012 ",\ join(',',@pid)) else {call dsp_event('WARNING: No Oracle sessions found for Oracle PIDs specified') call wait_exit() } } elsif compare('eq',$DDC_PID,'P') {# Get the PIDs of sessions connected as specified by UNIX PIDs (-U): var @pid = @DDC_PID call dsp_event("Client PIDs [For process ",join(',',@DDC_PID),"]:\012 ",\ join(',',@pid)) } elsif compare('eq',$DDC_PID,'S') {# Get the PIDs for the sessions specified var @pid = get_session_pids(@DDC_PID) if @pid call dsp_event("Client PIDs [For SID(s) ",join(',',@DDC_PID),"]:\012 ",\ join(',',@pid)) else {call dsp_event('WARNING: No Oracle sessions detected for SIDs ',\ join(',',@DDC_PID)) call wait_exit() } } elsif compare('eq',$DDC_PID,'U') {# Get the PIDs of sessions connected as specified by $DDC_USR var @pid = get_user_pids($DDC_USR) if @pid call dsp_event("Client PIDs [Username: ",$DDC_USR,"]:\012 ",join(',',@pid)) else {call dsp_event('WARNING: No oracle sessions detected for username ',$DDC_USR) call wait_exit() } } else var @pid = () # Analyze specified process identifiers loop $pid (@pid) {# Request a 10046 trace if exists($DDC_PRC{'T'}) {if $WAIT {job {import $pid call kip(get_wait('10046 trace (PID: ',$pid,')')) call clone_log() call dsp_event('Tracing (10046) a shadow process (PID: ',$pid,') ...') call collect_10046($pid) } } else {call dsp_event('Tracing (10046) a shadow process (PID: ',$pid,') ...') call collect_10046($pid) } sleep 5 } # Request a process state dump if exists($DDC_PRC{'P'}) {call dsp_event('Requesting a process state dump (PID: ',$pid,') ...') call collect_process_state($pid) } # Collect error stack if exists($DDC_PRC{'E'}) {call dsp_event('Requesting an error stack (PID: ',$pid,') ...') call collect_error_stack($pid) } # Launch an operating system trace if exists($DDC_PRC{'O'}) {var $fil = catFile(${OUT.E},concat($PRE,'po_',$pid,'.trc')) var $cmd = concat($TRC_CMD,' -o ',$fil,' -p ',$pid) if $WAIT {job {import $cmd,$fil,$pid,$PID call kip(get_wait('trace (PID: ',$pid,')')) call clone_log() call log_event('O/S trace written to: ',basename($fil)) call dsp_event('Command: ',$cmd) output | $cmd call create_lock($PID,'ddcpo',getOutputPid()) } } else {call log_event('Tracing with ',$TRC_PGM,' ...') call log_event('O/S trace written to: ',basename($fil)) call dsp_event('Command: ',$cmd) job {import $cmd,$PID output | $cmd call create_lock($PID,'ddcpo',getOutputPid()) } } } # Collect pfiles traces if exists($DDC_PRC{'F'}) {if $PFL_CMD var ($flg,$cmd) = (true,concat($PFL_CMD,' ',$pid)) else var ($flg,$dir) = (false,sprintf($PFL_DIR,$pid)) if $WAIT {job {import $cmd,$dir,$flg,$pid,$PID,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call kip(get_wait('process open files (PID: ',$pid,')')) call dsp_event('Waking up to take pfiles trace (PID: ', $pid,') ...') call dsp_event('Pfiles trace (PID: ',$pid,') - please wait ...') output E,concat('pf_',$pid,'.txt') if $flg {write '---+ Pfiles Trace for PID ',$pid call writeCommand($cmd) } else {write '---+ List of Open Files from ',$dir call statDir('n',$dir) } write $TOP var $rpt = basename(renderFile()) call dsp_event('Pfiles trace for ',$pid,' completed') call log_event('Pfiles trace written to: ',$rpt) call $lck->unlink } } else {call dsp_event('Writing process open files (PID: ',$pid,') ...') job {import $cmd,$dir,$flg,$pid,$PID,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call dsp_event('Pfiles trace (PID: ',$pid,') - please wait ...') output E,concat('pf_',$pid,'.txt') if $flg {write '---+ Pfiles Trace for PID ',$pid call writeCommand($cmd) } else {write '---+ List of Open Files from ',$dir call statDir('n',$dir) } write $TOP var $rpt = basename(renderFile()) call dsp_event('Pfiles trace for ',$pid,' completed') call log_event('Pfiles trace written to: ',$rpt) call $lck->unlink } } } # Collect pfiles traces if exists($DDC_PRC{'L'}) {var $cmd = concat($LDD_CMD,' ',$pid) if $WAIT {job {import $cmd,$pid,$PID,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call kip(get_wait('process dynamic libraries (PID: ',$pid,')')) call dsp_event('Waking up to take pldd trace (PID: ', $pid,') ...') call dsp_event('Pldd trace (PID: ',$pid,') - please wait ...') output E,concat('pl_',$pid,'.txt') write '---+ Pldd Trace for PID ',$pid call writeCommand($cmd) write $TOP var $rpt = basename(renderFile()) call dsp_event('Pldd trace for ',$pid,' completed') call log_event('Pldd trace written to: ',$rpt) call $lck->unlink } } else {call dsp_event('Writing process dynamic libraries (PID: ',$pid,') ...') job {import $cmd,$pid,$PID,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call dsp_event('Pldd trace (PID: ',$pid,') - please wait ...') output E,concat('pl_',$pid,'.txt') write '---+ Pldd Trace for PID ',$pid call writeCommand($cmd) write $TOP var $rpt = basename(renderFile()) call dsp_event('Pldd trace for ',$pid,' completed') call log_event('Pldd trace written to: ',$rpt) call $lck->unlink } } } # Collect stack traces if exists($DDC_PRC{'S'}) {var $cmd = concat($STK_CMD,' ',$pid) if $WAIT {job {import $cmd,$pid,$rpt,$PID,$TOC,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call kip(get_wait('process stack (PID: ',$pid,')')) call dsp_event('Waking up to take stack trace (PID: ', $pid,') ...') call dsp_event('Stack trace (PID: ',$pid,') - please wait ...') output E,concat('ps_',$pid,'.txt') write '---+!! Stack Trace for PID ',$pid write $TOC for $cnt (1,24) {write '---+ Stack Trace No ',$cnt call writeCommand($cmd) write $TOP } var $rpt = basename(renderFile()) call dsp_event('Stack trace for ',$pid,' completed') call log_event('Stack trace written to: ',$rpt) call $lck->unlink } } else {call dsp_event('Writing process stack (PID: ',$pid,') ...') job {import $cmd,$pid,$rpt,$PID,$TOC,$TOP var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() sleep 1 call dsp_event('Stack trace (PID: ',$pid,') - please wait ...') output E,concat('ps_',$pid,'.txt') write '---+!! Stack Trace for PID ',$pid write $TOC for $cnt (1,24) {write '---+ Stack Trace No ',$cnt call writeCommand($cmd) write $TOP } var $rpt = basename(renderFile()) call dsp_event('Stack trace for ',$pid,' completed') call log_event('Stack trace written to: ',$rpt) call $lck->unlink } } } } # Execute the custom scripts loop $fil (keys(%DDC_SQL)) {call dsp_event('Executing ',$fil,' ...') job {import $fil,$DDC_SLP,$PID,%DDC_SQL var $lck = create_lock($PID,'ddcps',getPid()) call clone_log() call setSqlTarget($[tgt]) if createBuffer('SQL','R',$fil) {var ($nam,$sql,$typ,@TTL,@HDR,%tbl) = () # Parse the file while getLine('SQL') {var $lin = chomp(last) if match($lin,'REM\s+ORADDC.(\w+)="(.*)"',true) {var ($key,$val) = last if match($val,'\w+(\s+\w+)*') var $tbl{lc($key)} = $val } elsif match($lin,'REM\s+ORADDC.TTL\[(\d+)\]="(.*)"',true) {var ($off,$val) = last var $TTL[$off] = $val } elsif match($lin,'REM\s+ORADDC.HDR\[(\d+)\]="(.*)"',true) {var ($off,$val) = last var $HDR[$off] = $val } else var $sql = join("\012", $sql,$lin) } var $typ = nvl($tbl{'typ'},'text') var $nam = nvl($tbl{'nam'},$DDC_SQL{$fil}) var $rpt = nvl($tbl{'rpt'},basename($fil)) # Execute the request if match($typ,'trace') {var $sql = join("\012",check_wait($nam),$sql,'oradebug tracefile_name') output E,concat('sql_',$rpt,'.tmp') call writeSql(bindSql($sql,$DDC_SLP,getPid())) var $rpt = getFile('/') if grepFile($rpt,'\.trc','if') {var $fil = trim(last) call dsp_event('(',$nam,') Done.') call log_event('Trace identifier: ',$nam,'=',$fil) } close } elsif match($typ,'data') {var $sql = join("\012",check_wait($nam),$sql) output E,concat('sql_',$rpt,'.dat') call writeSql($sql) if isCreated(true) {var $rpt = getRawLink(true) call dsp_event('(',$nam,') Done.') call log_event('Spooling to: ',$nam,'=',$rpt) } close } elsif match($typ,'wiki') {var $sql = join("\012",check_wait($nam),$sql) output E,concat('sql_',$rpt,'.txt') var $TTL = concat('---++!! ',$nam) call writeSql($sql) if isCreated(true) {var $rpt = renderFile() call dsp_event('(',$nam,') Done.') call log_event('Spooling to: ',$nam,'=',basename($rpt)) } } call deleteBuffer('SQL') } call $lck->unlink } } # Wait for trace completion call wait_exit() # Finalize the log if exists($DDC_DMP{'A'}) call check_hanganalyze() call collate_traces() if $WAIT call purge('e',$CLR,-1,0) debug 'ORADDC collection ended' call $[log]->render() echo 'ORADDC log: ',last =head1 SEE ALSO L, L, L =begin credits =over 10 =item RDA 4.11: Clive Bostock. =item RDA 4.12: Clive Bostock, Francois Lange. =item RDA 4.15: Clive Bostock. =item RDA 4.16: Clive Bostock. =item RDA 4.21: Takeyoshi Sasaki. =item RDA 4.25: Deepak Malik. =item RDA 4.27: Deepak Malik. =item RDA 4.28: Bob Caldwell, Michael Polaski. =item RDA 8.03: Girisha Madegowda. =item RDA 8.09: Sayed Muhammed Sha. =back =end credits =head1 COPYRIGHT NOTICE Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. =head1 TRADEMARK NOTICE Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners. =cut