# TLredo.ctl: Scans and Merges Redo Dump Records from Multiple Trace Files # $Id: TLredo.ctl,v 1.4 2015/05/29 06:11:26 RDA Exp $ # ARCS: $Header: /home/cvs/cvs/RDA_8/src/scripting/lib/collect/DB/TLredo.ctl,v 1.4 2015/05/29 06:11:26 RDA Exp $ # # Change History # 20150527 KRA Improve the documentation. =head1 NAME TOOL:TLredo - Scans and Merges Redo Dump Records from Multiple Trace Files =head1 DESCRIPTION This tool extracts redo dump records from multiple Oracle database trace files and merges them ordered by C and C. It produces a report with the merged redo records. It can produce a plain output file with the records in their original format to allow post-processing. Switches allow to refine the extraction process. =head1 REQUIREMENTS Must have one or more Oracle database trace files containing redo record dumps. =head1 USAGE This tool takes the corresponding trace files as input and some switches allow to refine the extraction process: -XRda [-v] run TLredo [-aho] [-r,...] ... [-v] run TLredo [-aho] [-r,...] ... =over 3 =item C<-a> Considers all redo records. By default, the tool skips all C redo records. =item C<-h> Collects redo and change headers only. Otherwise the full redo records including the change dumps are collected. When no restriction criteria is specified, this mode is enforced to reduce the output volume. =item C<-o> Produces a plain text output file with the collected and merged redo records, in the same format as original redo record. =item C<-r> Restricts redo records collected to those matching the restriction criteria. You can specify multiple restriction criteria separated by commas. It is not recommended to use the tool without any restriction filter, as it may lead to a huge report volume size, which may be impractical to manage. =back In verbose mode, the tool shows a dot progress bar while scanning trace files for each 1000 records processed. =cut options ahor* use Buffer use Collect section tool echo tput('bold'),'Processing REDO tool module ...',tput('off') # Reject request without files if !@arg {echo 'No files specified.' return } # Analyze the options if $opt{'r'} var ($hdr,$pat,$sel) = (exists($opt{'h'}),join('|',@{last}),false) else {echo 'WARNING: No restriction filter specified. Headers-only report enforced.' var ($hdr,$pat,$sel) = (true,false,true) } var ($prc,$skp,$vrb,%cnt,%rdr) = (0,false,$[COL]->is_verbose) # Define the parsing code code beg_record {if $vrb {if !expr('%',incr($prc),1000) call $[DSP]->dsp_string('','.',0) } if and(exists($cur->{'scn'}),$cur->{'sel'}) var $rdr{$cur->{'scn'},$cur->{'sub'},incr($cnt),$nam} = $cur->{'rec'} var $cur = {rec => [],sel => $sel} return 0 } code end_record {call push($cur->{'rec'},parseBuffer()) return 0 } code set_record {var $cur->{'scn'} = parseHit(0) var $cur->{'sub'} = parseHit(1) return 0 } code skp_record {var $cur = {rec => [],sel => $sel} incr $dis return 1 } # Define the parser call parseReset() call parseBegin('TOP','^DUMP (OF )?REDO','REDO') call parseBegin('REDO','^REDO RECORD','REC','GRP') call parseInfo('REC','beg',&beg_record) call parseInfo('REC','buf',-1) call parseInfo('REC','end',&end_record) call parsePattern('REC','SCN: *([^ ]*) *SUBSCN: *([^ ]*) *',&set_record) if $pat call parsePattern('REC',$pat,code($cur->{'sel'} = true,0)) call parseBegin('REDO','^CHANGE #\d+','CHG','GRP') if !$opt{'a'} call parsePattern('CHG','^CHANGE #1 MEDIA RECOVERY MARKER',&skp_record) if $pat call parsePattern('CHG',$pat,code($cur->{'sel'} = true,0)) if $hdr call parsePattern('CHG','^CHANGE #\d+',code(push($cur->{'rec'},line),0)) else {call parseInfo('CHG','buf',-1) call parseInfo('CHG','end',&end_record) } call parseBegin('REDO','^END OF DUMP REDO','END','GRP') call parseInfo('END','beg',code(parseQuit())) call parseBegin('REDO','^END OF REDO DUMP','NXT','GRP') call parsePattern('NXT','.',2) # Analyze the redo dump files loop $fil (@arg) {var $nam = basename($fil) call $[DSP]->dsp_string('',"Parsing redo records from ${VAR.nam} file ...",0) if createBuffer('RDO','R',$fil) {var ($cnt,$cur,$dis) = (0,{rec => [],sel => $sel},0) call parse('RDO') call eval(&beg_record) var $cnt{$fil} = $cnt echo '' debug 'Selected ',$cnt,' redo records from ',$nam,' file.' if $dis debug 'Discarded ',$dis,' MEDIA RECOVERY MARKER redo records.' call deleteBuffer('RDO') } else echo "\012WARNING: File not accessible: ",$fil } # Generate the report and the output file when requested debug cond($opt{'o'},'Generating report and output file ...',\ 'Generating report ...') call setAbbr('DB_REDO_') call purge('E','.',-1) output E,report write '---+!! Redo Log Records' write '---++!! Processed files:' loop $fil (@arg) write ' * Extracted ',$cnt{$fil},' redo records from ',encode($fil) if $pat {write '---++!! Restricted to Redo Records containing at least one of the \ following values:' loop $res (split('\|',$pat)) write ' * ',encode($res) } if $hdr write '---### - Only Redo and Change Headers' if !$opt{'a'} write '---### - MEDIA RECOVERY MARKER Redo Records discarded' prefix write '|*SCN / SUBSCN* |*Redo Record Dump* |*Trace File Containing the \ Redo Record* |' if $opt{'o'} var $dat = $[OUT]->add_report('e','data',0,'.dat') loop $scn (keys(%rdr)) {loop $sub (keys($rdr{$scn},'IA')) {loop $cnt (keys($rdr{$scn,$sub},'IA')) {loop $nam (keys($rdr{$scn,$sub,$cnt})) {call $dat->write(join("\012",@{$rdr{$scn,$sub,$cnt,$nam}},'')) write '|',$scn,' / ',$sub,' |',\ join('%BR%',map($rdr{$scn,$sub,$cnt,$nam},code(encode(last)))),' |',\ encode($nam),' |' } } } } if isCreated(true) {call renderReport() dump 'Report file: ',last } if $dat->is_created(true) dump 'Output file: ',$dat->get_path =begin credits =over 10 =item RDA 8.07: Gabriel Alonso, Miguel Atienza, David Loinaz. =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