home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
tarv314.zip
/
TARRR.CMD
< prev
next >
Wrap
OS/2 REXX Batch file
|
1993-05-14
|
116KB
|
2,792 lines
/* ************************************************************************ */
/* MODULE NAME: TaRRR */
/* */
/* DESCRIPTIVE NAME: Table Repair/Recover/ReConstruction Tool */
/* Control Program */
/* */
/* LPP NAME: Standalone Tool */
/* */
/* DESCRIPTION: This routine is responsible for the determination */
/* of the local database that is to be inspected and */
/* TaRRR'd. It processes the arguments passed as */
/* input to the TaRRR Tool and supervises the entire */
/* repair in the appropriate sequence. */
/* */
/* This module will call the TARNSPEC for the repair */
/* and inspection of the table. After the TARNSPEC, */
/* it will run through recovery phase and database */
/* will be ready for the reconstruction. */
/* It then initiates execution of the Page */
/* ReConstruction Phase of Repair. This phase */
/* resolves the UnMatched Pointer Records and */
/* generates the Lost Row Report. This program will */
/* decide if reorg is required after reconstruction, */
/* if reorg is required, it will prompt user for */
/* reorg. The final step is the Usable Database */
/* Inspection phase. If the user has requested */
/* repair of one or more database tables, this */
/* program will prompt the user to determine */
/* whether or not Usable Database Inspection should */
/* be executed. If the user has requested an */
/* inspection only, then this program will bypass */
/* the repair, recovery and reconstruction phases */
/* and execute the usable database inspection only. */
/* Originally, this inspection phase was only */
/* intended for usable databases; however, it has */
/* subsequently been changed so a user could */
/* request inspection of a database that cannot be */
/* opened. */
/* */
/* */
/* DEPENDENCIES: */
/* SYSTEM CONFIRUATION: */
/* - OS/2 EE 1.2+ */
/* */
/* LANGUAGE INTERPRETER: */
/* - OS/2 Rexx Interpreter */
/* */
/* PREREQUISTIES: None */
/* */
/* */
/* RESTRICTIONS: None */
/* */
/* INPUT: Database name */
/* Repair Bias */
/* Fully-Qualified Single Table Repair Filename */
/* Single Page Repair Number */
/* Report filename */
/* */
/* */
/* OUTPUT: */
/* Repaired database table(s) */
/* ReBuilt index(es) */
/* Repair Report written to specified file */
/* Return Code stored in REXX host variable 'result' */
/* */
/* HOST LANGUAGE: OS/2 Rexx */
/* */
/* LAST CHANGE DATE: 01/12/92 */
/* */
/* Version Date Programmer Reason */
/* ------------------------------------------------------------------------ */
/* 3.04 10/20/92 D.R. Snow Enhanced messages in */
/* TaRRR and Resetlog. */
/* Warn of possible data */
/* loss. */
/* 3.10 10/31/92 D.R. Snow Whenever repair specified, */
/* warn of possible data loss. */
/* Let user end program. */
/* 3.11 12/15/92 D.R. Snow Add EERESET.CMD */
/* 3.13 01/06/93 D.R. Snow Allow Meta flag to be 1 or */
/* 0, and allow new unique */
/* specifier in index files. */
/* 3.14 01/06/93 D.R. Snow Stop processing if it is a */
/* DB2/2 database. */
/* */
/* ************************************************************************ */
/*********************************************
turn off trace and echo
*********************************************/
'@echo off'
TRACE OFF
/*********************************************
Define Flags to Determine Open File Status
Initialize Constant
*********************************************/
rpt_open = 'NO' /* Open Status for Report File */
con_open = 'NO' /* Open Status for Configuration File */
boot_open = 'NO' /* Open Status for BOOT File */
dep_open = 'NO' /* Open Status for .DEP File */
/*********************************************
Initialize Phase Status Flags
*********************************************/
start_using = 'NO' /* Start Using database flag */
inspec_step = 'YES' /* Default status for inspection */
recon_step = 'YES' /* Default status for reconstruction */
reorg_step = 'YES' /* Default status for table reorg */
numeric digits 15 /* Set Precision for the arithmetic operations */
dbm_already_started = 'YES' /* Flag to indicate if DbMgr already started
prior to entering this program */
max_tbname_len = 27 /* Max table name length (8.18) */
cr_lf = d2c(13) || d2c(10) /* Line End characters */
global_return = 0 /* Final return code for TaRRR */
cat_flag = 'NO' /* System Catalog Damaged flag */
'rxqueue /clear' /* clear queue */
/*********************************************
Define all the error messages.
*********************************************/
TAR0006I = "TaRRR Completed: Data rows were lost and known problems exist " || ,
"in the database."
TAR0004I = "TaRRR Completed: Known problems exist in the database."
TAR0002I = "TaRRR Completed: Data rows were lost."
TAR0000I = "TaRRR Completed: No known problems remain and no lost rows " || ,
"were found."
TAR0002N = "A Disk Full error occurred during repair; the TaRRR Tool " || ,
"did not complete."
TAR0004N = "A Write Protect error occurred during repair; the TaRRR Tool " || ,
"did not complete."
TAR0006N = "A report file I/O error occurred; the TaRRR Tool did not " || ,
"complete."
TAR0008N = "A temporary file I/O error occurred; the TaRRR Tool did not " || ,
"complete."
TAR0010N = "A potential file allocation problem has been detected. " || ,
"The TaRRR Tool did not complete."
TAR0012N = "An I/O repair failure occurred. The database is in an " || ,
"indeterminate state."
TAR0014N = "A system catalog was damaged. The database may not be usable."
TAR0016A = "A system file I/O error occurred in "
TAR0016B = cr_lf || "The TaRRR Tool did not complete. " || ,
cr_lf || "Verify that all processes are disconnected " || ,
"from the database. "
/* ****
The following message has been replaced with the two previous message
parts so that the file name may be inserted into the message text.
TAR0016N = "A system file I/O error occurred. The TaRRR Tool did not " || ,
"complete. "
**** */
TAR0018N = "An unexpected memory allocation error occurred; " || ,
"the TaRRR Tool did not complete."
TAR0032N = "The database name was not found in the database directories."
TAR0042N = "The table filename is not a valid database table file. "
TAR0044N = "The table filename does not exist. "
TAR0052N = "The table page number is not a valid page number. "
TAR0054N = "The table page number does not exist in the table file."
TAR0062N = "The report file name is not a valid OS/2 filename. "
TAR0064N = "The path for the report file does not exist. "
TAR0066N = "The report filename/extension contains words reserved " || ,
"for temporary repair files."
TAR0072N = "Database Manager registration error"
TAR0082N = "TaRRR cannot be run against a DB2/2 database."
/* **************** Define some addition return codes ******************* */
/* RC = 80 Invalid repair bias specified. */
/* *************** End define some addition return codes **************** */
/*********************************************
Define all the report header and text
*********************************************/
eqlines = '==================================================' || ,
'============================' /* Report Delimiter Lines */
dashline= '--------------------------------------------------' || ,
'----------------------------' /* Report Delimiter Lines */
title = ' TaRRR (V3.14) Report - ' /* Report Title */
dbtext= ' Database Name: ' /* Damaged Database */
dbsubtext = ' Database Subdirectory: ' /* Damaged Database Subdir. */
biatxt = ' Repair Bias: ' /* Repair Bias */
biasold = 'Retain Existing Records (OLD)'
biasnew = 'Recover from Write-Ahead Log (NEW)'
biasnsp = 'Database Inspection Only (NSPEC)'
biasnspx= 'Database Inspection with Index ReBuild (NSPECX)'
frctxt = ' ** Force Option Specified ** ' /* Force Option text */
dbcstxt= ' ** DBCS Database ** ' /* DBCS Database text*/
/* Db Cfg Indicators */
cfgtxt = 'One or more of the following Database Configuration Indicators have been reset: '||cr_lf||,
' Copy Protect '||cr_lf||,
' Enable Log Retain '||cr_lf||,
' Enable Log Exit '||cr_lf||,
' Automatic Restart '||cr_lf
tbtext = ' Data Table Filename: ' /* Damaged Table File */
indtext = ' Index Name: ' /* Index Name */
tbname = ' Table Name: ' /* Damaged Table Name */
pgtext = ' Damaged Page Number: ' /* Damaged Page Number */
repbeg = 'Repair Phase Start: ' /* Inspection Phase Start */
repend = 'Repair Phase End: ' /* Inspection Phase End */
recbeg = 'ReConstruction Phase Start: ' /* Reconstruction Phase Strt */
recend = 'ReConstruction Phase End: ' /* Reconstruction Phase End */
orgbeg = 'ReOrg Phase Start: ' /* Reorg Phase Start */
orgend = 'ReOrg Phase End: ' /* Reorg Phase End */
datbeg = 'Table Inspection Phase Start: ' /* Tbl Inspection Phase Start*/
datend = 'Table Inspection Phase End: ' /* Tbl Inspection Phase End */
chxbeg = 'Index Inspection Phase Start: ' /* Idx Inspection Phase Start*/
chxend = 'Index Inspection Phase End: ' /* Idx Inspection Phase End */
revbeg = 'Recovery Phase Start: ' /* Recovery Phase Start */
revend = 'Recovery Phase End: ' /* Recovery Phase End */
revsuccess = '... Recovery Successful' /* Recovery Successful */
orgsuccess = '... ReOrg Successful ' /* ReOrg Successful */
runsuccess = '... Runstat Successful ' /* RunStat Successful */
rbxbeg = 'Index ReBuild Phase Start: ' /* Index ReBuild Phase Start */
rbxend = 'Index ReBuild Phase End: ' /* Index ReBuild Phase End */
prctxt = '....Processing file ' /* Progress message */
reptxt = ' ....No further repair needed' /* Progress repair message */
rcntxt = ' ....No rows lost' /* Progress recon message */
lsttxt = ' ....*** Rows lost ***' /* Progress recon message */
rogtxt = '....Processing table ' /* Progress message */
cmptxt = ' ....Complete' /* Progress reorg message */
goodtxt = ' ....No errors found' /* Progress success message */
errtxt = ' ....*** Errors found ***' /* Progress error message */
reorg_text = cr_lf||cr_lf||,
" ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
" ║ ** NOTICE ** NOTICE ** NOTICE ** NOTICE ** NOTICE ** ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ║ THE TABLE NEEDS TO BE REORGANIZED WHENEVER POSSIBLE ║ "||cr_lf||,
" ║ Would you like to ReOrg the Table now? (y/n) ║ "||cr_lf||,
" ║ If so, type 'y' and press ENTER; ║ "||cr_lf||,
" ║ Otherwise, type 'n' and press ENTER. ║ "||cr_lf||,
" ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
cr_lf ||cr_lf|| cr_lf
sqlcheck_text= cr_lf||cr_lf||,
" ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
" ║ ** NOTICE ** NOTICE ** NOTICE ** NOTICE ** NOTICE ** ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ║ USABLE DATABASE INSPECTION ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ║ Would you like to run a final inspection of the ║ "||cr_lf||,
" ║ specified table(s) and index(es)? (y/n) ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ║ If so, type 'y' and press ENTER; ║ "||cr_lf||,
" ║ Otherwise, type 'n' and press ENTER. ║ "||cr_lf||,
" ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
cr_lf ||cr_lf|| cr_lf
dbname_text = cr_lf||cr_lf||,
" ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ║ Please type the input Database Name and press ENTER: ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
cr_lf ||cr_lf|| cr_lf
rptname_text = cr_lf || cr_lf || cr_lf ||,
" ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ║ Please type the input Report Filename and press ENTER: ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
cr_lf ||cr_lf|| cr_lf
dbcfg_text= cr_lf||cr_lf||,
" ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
" ║ ** NOTICE ** NOTICE ** NOTICE ** NOTICE ** NOTICE ** ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ║ CHANGE TO DATABASE CONFIGURATION ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ║ One or more of the following Database Configuration Indicators is ║ "||cr_lf||,
" ║ being reset to regulate the repair environment: ║ "||cr_lf||,
" ║ Copy Protect ║ "||cr_lf||,
" ║ Enable Log Retain ║ "||cr_lf||,
" ║ Enable Log Exit ║ "||cr_lf||,
" ║ Automatic Restart ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ║ If you want these indicators active, you will have to set them in ║ "||cr_lf||,
" ║ the Database Configuration after this repair program completes. ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
cr_lf ||cr_lf|| cr_lf
warn_dataloss= cr_lf||cr_lf||,
" ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
" ║ ** WARNING ** WARNING ** WARNING ** WARNING ** WARNING ** ║ "||cr_lf||,
" ║ ║ "||cr_lf||,
" ║ You have asked to repair the database! ║ "||cr_lf||,
" ║ ╔════════════════════════════════╗ ║ "||cr_lf||,
" ║ ║ ║ ║ "||cr_lf||,
" ║ ║ DATA MAY BE LOST, ║ ║ "||cr_lf||,
" ║ ║ DO YOU WISH TO CONTINUE? ║ ║ "||cr_lf||,
" ║ ║ ║ ║ "||cr_lf||,
" ║ ╚════════════════════════════════╝ ║ "||cr_lf||,
" ║ If so, type 'y' and press ENTER; ║ "||cr_lf||,
" ║ Otherwise, type 'n' and press ENTER. ║ "||cr_lf||,
" ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
cr_lf ||cr_lf|| cr_lf
/* *********************************************************************** */
/*********************************************
Get the input arguments, ignore the extra
arguments or non-sense arguments entered by user.
*********************************************/
single_tab = 'NO' /* default single table option */
single_page = 'NO' /* default single page option */
bias = 'NEW' /* default bias option */
parse upper arg dbname .
parse upper arg . '/B:' bias .
parse upper arg . '/T:' fname .
parse upper arg . '/P:' inpage .
parse upper arg . '/R:' rptname .
parse upper arg . '/O:' reorg_opt .
parse upper arg . '/I:' nspec_opt .
parse upper arg . '/F:' force_opt .
/*********************************************
Check the Program Input Arguments
*********************************************/
if dbname = '?' then
do
global_return = 0 /* The TaRRR execution was */
/* successful. Help displayed. */
call general_help /* Display the call syntax */
signal xit /* Signal to exit. */
end
/*********************************************
Register SQLDBS with REXX
*********************************************/
/* Check if SQLDBS function is currently registered */
if Rxfuncquery('SQLDBS') \= 0 then
do
/* Register SQLDBS function */
rcy = Rxfuncadd('SQLDBS','SQLAR','SQLDBS')
if rcy \= 0 then
do
global_return = -72
say TAR0072N
signal xit
end
end /* end if */
/*********************************************
Register SQLEXEC with REXX
*********************************************/
/* Check if SQLEXEC function is currently registered */
if Rxfuncquery('SQLEXEC') \= 0 then
do
/* Register SQLEXEC function */
rcy = Rxfuncadd('SQLEXEC','SQLAR','SQLEXEC')
if rcy \= 0 then
do
global_return = -72
say TAR0072N
signal xit
end
end /* end if */
/*********************************************
Start Database Manager
*********************************************/
call SQLDBS 'START DATABASE MANAGER'
if (sqlca.sqlcode \= 0) & (sqlca.sqlcode \= -1026) then
call sqlsit /* Start Database Manager error encountered */
else
do
if (sqlca.sqlcode = 0) then /* DbMgr not previously started */
dbm_already_started = 'NO'
end
/*********************************************
Check that we are not running against a back
level version of the database manager.
*********************************************/
tokens.0 = 2
tokens.1 = 101
call SQLDBS 'GET DATABASE MANAGER CONFIGURATION using :tokens'
if (sqlca.sqlcode \= 0) then
do
global_return = -82 /* Set return to message no. */
say TAR0082N /* Tell user cannot run against back*/
/* level of DB. */
signal xit /* Exit if wrong version... */
end
if (tokens.2 > 768) then /* DB2/2 is release 0x400 */
do
global_return = -82 /* Set return to message no. */
say TAR0082N /* Tell user cannot run against back*/
/* level of DB. */
signal xit /* Exit if wrong version... */
end
/*********************************************
Verify the Input Parameters specified on
TaRRR Command
Note: Will also open the Report File, so
it needs to be after STARTDBM
*********************************************/
call chkargs
/*********************************************
Check for Database Inspection Only
*********************************************/
if ((bias = 'NSPEC') | (bias = 'NSPECX')) then
do
inspec_step = 'NO' /* Do not execute the Repair Phase */
recon_step = 'NO' /* Do not execute the ReConstruction Phase */
reorg_step = 'NO' /* Do not prompt for the ReOrg Phase */
end
else /* User requested database repair Bias = OLD or NEW */
do
'cls' /* Clear the screen */
say warn_dataloss /* Warn of possible data loss */
pull w_resp /* Get answer, continue or not */
if ( (w_resp \= 'Y') & (w_resp \= 'y') ) then
do
global_return = 0 /* The TaRRR execution was successful. */
signal xit /* Signal to exit. */
end
end /* Continue with Database repair */
/*********************************************
Write the Report Header for TaRRR
*********************************************/
call rpthdr
/*********************************************
Read the database signature and the release
number from Database Configuration File
*********************************************/
call cfgread
/*********************************************
call CATREAD get syscatalog fid
*********************************************/
call catread
/*********************************************
If this is Inspection Mode Only, the db
will be connected later.
*********************************************/
if ((bias \= 'NSPEC') & (bias \= 'NSPECX')) then
do
/*********************************************
Start Using the Database in Exclusive Mode
*********************************************/
/* Close Report File in case the Start Using causes a Logon Process
to be initiated */
call ficlo 'REPORT'
/* Connect to the Database */
call sqldbs 'START USING DATABASE ' dbname ' IN EXCLUSIVE MODE'
/* Re-Open the Report File */
call filop 'REPORT'
/* Error exit if Start Using is Unsuccessful because of some other error
than Db Needs Recovery when Repair Bias is "OLD" or "NEW" */
if ((sqlca.sqlcode \= 0) & (sqlca.sqlcode \= -1015)) then
call sqlxit
if sqlca.sqlcode = 0 then
do
start_using = 'YES' /* Start Using successful flag */
/* */
/* Note: The Stream Command cannot be used on Cruiser because the */
/* wildcard character support was removed. */
/* if (stream(db_full_path || '*.DRR','c','query exist') = '') then */
/* */
'tarfqry ' db_full_path || '*.DRR'
if (rc \= 0) then
drr_rc = 'NO'
else
drr_rc = 'YES'
/* */
/* Note: The Stream Command cannot be used on Cruiser because the */
/* wildcard character support was removed. */
/* if (stream(db_full_path || '*.DEP','c','query exist') = '') then */
/* */
'tarfqry ' db_full_path || '*.DEP'
if (rc \= 0) then
dep_rc = 'NO'
else
dep_rc = 'YES'
if drr_rc = 'YES' then /* .DRR file exists */
do
inspec_step = 'NO' /* no inspection needed */
if dep_rc = 'NO' then /* if no .DEP exist */
recon_step = 'NO' /* no reconstruction needed */
end
end
end
/*********************************************
call TARNSPEC
*********************************************/
if inspec_step = 'YES' then /* If TARNSPEC is required */
do
if single_tab = 'YES' then /* If single table repair */
do
/*********************************************
Log the Inspection Phase Start Heading
*********************************************/
/* Display progress messages */
say cr_lf || repbeg
dsp_rc = charout(,prctxt || fname)
/* Log report data */
call putout repbeg || time('L')
call putout ' '
call putout tbtext || fname
if single_page = 'YES' then
call putout pgtext || inpage
call putout ' '
call inspec /* call tarnspec */
/*********************************************
Log the Inspection Phase End Heading
*********************************************/
call putout cr_lf || ' '
call putout repend || time('L')
call putout ' '
end
else /* Multiple Table Repair */
do
/* check if any .DAT file exist first */
/* */
/* Note: The Stream Command cannot be used on Cruiser because the */
/* wildcard character support was removed. */
/* */
/* if (stream(db_full_path || 'SQL*.DAT','c','query exist') \= '') then */
'tarfqry ' db_full_path || 'SQL*.DAT'
if (rc == 0) then
do
/*********************************************
Log the Inspection Phase Start Heading
*********************************************/
say cr_lf || repbeg
call putout repbeg || time('L')
call putout ' '
'rxqueue /clear' /* clear queue */
/* Queue all .DAT Files in the database subdirectory */
'dir/f ' db_full_path||'SQL*.DAT | rxqueue /fifo'
do queued()
pull fname /* Get each .DAT file */
/* Display progress message */
dsp_rc = charout(,prctxt || fname)
/* Inspect & Repair the file */
call inspec
end
/*********************************************
Log the Inspection Phase End Heading
*********************************************/
call putout cr_lf || ' '
call putout repend || time('L')
call putout ' '
end /* if any .DAT file exist */
end /* not single table option */
call putout dashline
/*********************************************
Recovery Phase must only be executed if
the previous Start Using was Unsuccessful
because the Database Needed Recovery
*********************************************/
if start_using = 'NO' then
do
/*********************************************
Log the Recovery Phase Start Heading
*********************************************/
say cr_lf || revbeg
call putout ' '
call putout revbeg || time('L')
call putout ' '
/*********************************************
Recover the Database via the Write-Ahead Log
*********************************************/
call sqldbs 'RESTART DATABASE ' dbname
if sqlca.sqlcode \= 0 then
call sqlxit
/*********************************************
Log the Recovery Phase End Heading
*********************************************/
call putout revsuccess
call putout ' '
call putout revend || time('L')
call putout ' '
call putout dashline
/*********************************************
Start Using the Database in Exclusive Mode
*********************************************/
call sqldbs 'START USING DATABASE ' dbname ' IN EXCLUSIVE MODE'
if sqlca.sqlcode \= 0 then
call sqlxit
start_using = 'YES'
end /* Database Needed Recovery */
end /* if inspec_step = 'YES' */
/*********************************************
Start the ReConstruction Phase
*********************************************/
if recon_step = 'YES' then /* If TARRECON is required */
do
/* check if any .DEP file exist first */
/* */
/* Note: The Stream Command cannot be used on Cruiser because the */
/* wildcard character support was removed. */
/* */
/* if (stream(db_full_path || '*.DEP','c','query exist') \= '') then */
'tarfqry ' db_full_path || '*.DEP'
if (rc == 0) then
do
/*********************************************
Log the ReConstruction Phase Start Heading
*********************************************/
say cr_lf || recbeg
call putout ' '
call putout recbeg || time('L')
call putout ' '
'rxqueue /clear' /* clear queue */
'dir/f ' db_full_path||'*.DEP | rxqueue /fifo' /* find all .DEP */
do queued()
/* Determine the file name to be reconstructed */
pull depname /* get each .DEP */
tmpfn = FILESPEC('name',depname)
fname = db_full_path || substr(tmpfn,1,pos('.',tmpfn)) || 'DAT'
/* Display progress message */
dsp_rc = charout(,prctxt || fname)
/* ReConstruct the table file */
call recon
end
/*********************************************
Log the ReConstruction Phase End Heading
*********************************************/
call putout ' '
call putout recend || time('L')
call putout ' '
call putout dashline
end /* if .DEP exist */
end
if (start_using = 'YES') then
do
/*********************************************
Issue STOP USING
*********************************************/
call sqldbs 'STOP USING DATABASE '
if sqlca.sqlcode \= 0 then
call sqlxit
start_using = 'NO'
end
/* If the user has not specified the "Inspection Only" Bias option */
if reorg_step = 'YES' then
do
/*********************************************
Prompt for Reorg of Table if necessary
*********************************************/
reorg_decision = 'N' /* default is NO */
/* Verify that there are tables needing ReOrg */
/* */
/* Note: The Stream Command cannot be used on Cruiser because the */
/* wildcard character support was removed. */
/* */
/* if (stream(db_full_path || '*.DRR','c','query exist') \= '') then */
'tarfqry ' db_full_path || '*.DRR'
if (rc == 0) then
do
/* Determine user response from Automatic ReOrg Option if specified */
select
/* Affirmative Automatic ReOrg Option specified */
when reorg_opt = 'YES' then do
reorg_decision = 'Y'
end
/* Negative Automatic ReOrg Option specified */
when reorg_opt = 'NO' then do
reorg_decision = 'N'
end
/* Automatic ReOrg Option not specified, thus user prompted */
when reorg_opt = '' then do
/* Prompt until a valid response if provided ("Y" or "N") */
do forever
'cls'
say reorg_text
pull reorg_decision
/* Check for a valid response */
if reorg_decision = 'Y' | reorg_decision = 'N' then
leave
end
end
end
if (reorg_decision = 'Y') then
do
/*********************************************
Log the ReOrg Phase Start Heading
*********************************************/
say cr_lf || orgbeg
call putout ' '
call putout orgbeg || time('L')
call putout ' '
/*********************************************
Start Using the Database in Exclusive Mode
*********************************************/
call sqldbs 'START USING DATABASE ' dbname ' IN EXCLUSIVE MODE'
if sqlca.sqlcode \= 0 then
call sqlxit
start_using = 'YES'
/*********************************************
Check each .DRR file in the database directory
*********************************************/
'rxqueue /clear' /* clear queue */
'dir/f ' db_full_path||'*.DRR | rxqueue /fifo'
do queued()
pull drrname
fname = db_full_path || substr(FILESPEC('name',drrname),1,,
pos('.',FILESPEC('name',drrname)))||'DAT'
call querytb /* get full table name */
call putout ' '
call putout tbname || full_tname
/* Display progress message */
dsp_rc = charout(,rogtxt || full_tname || ,
copies(' ', max_tbname_len - length(full_tname)) )
call SQLDBS 'REORG TABLE ' || full_tname || ' IN ' || dbname
if sqlca.sqlcode \= 0 then
call sqldump
else
call putout orgsuccess
'erase ' drrname /* erase .DRR file */
call SQLDBS 'RUNSTATS ON TABLE ' || full_tname || ,
' AND INDEXES ALL '
if sqlca.sqlcode \= 0 then
call sqldump
else
call putout runsuccess
/* Display the completion progress message */
dsp_rc = charout(,cmptxt || cr_lf)
end /* for each .DRR table */
/*********************************************
Issue STOP USING
*********************************************/
call sqldbs 'STOP USING DATABASE '
if sqlca.sqlcode \= 0 then
call sqlxit
start_using = 'NO'
/*********************************************
Log the ReOrg Phase End Heading
*********************************************/
call putout ' '
call putout orgend || time('L')
call putout ' '
call putout dashline
end /* If reorg decision is Yes */
else
do
'erase ' db_full_path||'*.DRR' /* erase all .DRR file */
end /* If reorg decision is NO */
end
end
/* The next phase has been previously called the Usable Database Inspection */
/* Originally, this phase was guaranteed to have a usable database on which */
/* to operate; however, it has been changed to allow inspection of even */
/* databases which cannot be opened. Thus, even though it is still called*/
/* the Usable Database Inspection in some places to distinguish it from */
/* the initial inspection phase of repair, it does now allow the */
/* inspection of databases which cannot be connected to via a Start Using.*/
/* If "Inspection Only" Bias option specified, then no prompt */
if ((bias = 'NSPEC') | (bias = 'NSPECX')) then
sqlcheck_decision = 'Y'
else
/* Repair has been done previously, so prompt for further inspection */
do
/* Determine user response from Automatic Inspection Option if specified */
select
/* Affirmative Automatic Inspection Option specified */
when nspec_opt = 'YES' then do
sqlcheck_decision = 'Y'
end
/* Negative Automatic Inspection Option specified */
when nspec_opt = 'NO' then do
sqlcheck_decision = 'N'
end
/* Automatic Inspection Option not specified, thus user prompted */
when nspec_opt = '' then do
/*********************************************
Prompt for Usable Database Inspection
*********************************************/
/* Prompt until a valid response is provided ("Y" or "N") */
do forever
'cls'
say sqlcheck_text
pull sqlcheck_decision
/* Check for valid response */
if sqlcheck_decision = 'Y' | sqlcheck_decision = 'N' then
leave
end
end
end
end
if sqlcheck_decision = 'Y' then
do
/*********************************************
Log the Usable Database Inspection
Phase Start Heading
*********************************************/
say cr_lf || datbeg
call putout ' '
call putout datbeg || time('L')
call putout ' '
/*********************************************
Start Using the Database in Exclusive Mode
Note: The reason for the Start Using here is retrieving
the Table Names from the Systables Catalog in
order to relate the Table Name with the OS/2
Filename for the user.
If the Start Using Fails (particularly in Inspection Only
Mode), it is sometimes beneficial for the user to
continue the inspection even though the Table Names
cannot be retrieved.
*********************************************/
/* Close Report File in case the Start Using causes a Logon Process
to be initiated */
/* Note: This could only happen here when the user has chosen the
"Inspection Only" mode */
call ficlo 'REPORT'
call sqldbs 'START USING DATABASE ' dbname ' IN EXCLUSIVE MODE'
call filop 'REPORT' /* Re-open the Report File */
/* Now that Report File is open, Check the Start Using return code */
if sqlca.sqlcode \= 0 then
call sqldump /* Record error and continue inspection */
else
start_using = 'YES' /* Indicate that database is connected */
/*********************************************
Inspect the specified Table(s) in the Usable Database
*********************************************/
/* Verify that the appropriate table files still exist */
/* */
/* Note: The Stream Command cannot be used on Cruiser because the */
/* wildcard character support was removed. */
/* */
/* (stream(db_full_path || 'SQL*.DAT','c','query exist') \= '') ) | , */
/* */
'tarfqry ' db_full_path || 'SQL*.DAT'
if ( single_tab = 'NO' & ,
(rc == 0) ) | ,
( single_tab = 'YES' & ,
(stream(fname,'c','query exist') \= '') ) then
do
'rxqueue /clear' /* clear queue */
if single_tab = 'YES' then
/* Push the table filename to be inspected on queue */
push fname
else
/* Check each .DAT file in the database directory */
'dir/f ' db_full_path||'SQL*.DAT | rxqueue /fifo'
do queued()
pull fname
call querytb /* full_tname will have table name */
/* Display progress message */
/* Note: The progress message for a Usable Database contains */
/* the Table Name since it can be retrieved from the */
/* SYSTABLES Catalog; the progress message for a */
/* Database that cannot be connected to contains the */
/* filename instead of the table name. */
if (start_using = 'YES') then
dsp_rc = charout(,rogtxt || full_tname || ,
copies(' ', max_tbname_len - length(full_tname)) )
else
dsp_rc = charout(,prctxt || fname)
call ficlo 'REPORT' /* close the report file */
'tarchdat ' full_tname fname rptname db_signature
tarchdat_rc = rc
/* Display progress completion message for file */
if tarchdat_rc = 0 then /* No errors found */
dsp_rc = charout(,goodtxt || cr_lf)
else /* Errors found */
dsp_rc = charout(,errtxt || cr_lf)
call filop 'REPORT' /* open the report file */
call handle_error tarchdat_rc
end
end
/*********************************************
Log the Usable Database Inspection Phase End Heading
*********************************************/
call putout ' '
call putout datend || time('L')
call putout ' '
call putout dashline
/*********************************************
Issue STOP USING
*********************************************/
if (start_using = 'YES') then
do
call sqldbs 'STOP USING DATABASE '
if sqlca.sqlcode \= 0 then
call sqldump
else
start_using = 'NO'
end
/*********************************************
Log the Usable Database Index Inspection Phase Start Heading
*********************************************/
say cr_lf || chxbeg
call putout ' '
call putout chxbeg || time('L')
call putout ' '
/*********************************************
Inspect the appropriate index(es)
*********************************************/
/* If the Single Table Option was specified */
if single_tab = 'YES' then
do
/* Create the corresponding index filename */
fndrv = FILESPEC("drive", fname) /* Drive of the Table File Name */
fnpath = FILESPEC("path", fname) /* Path of the Table File Name */
tmpfn = FILESPEC("name", fname) /* Fname/Ext of Table File Name */
indname = fndrv || fnpath || substr(tmpfn, 1, pos('.', tmpfn)) || 'INX'
end
/* Verify that the appropriate index files still exist */
/* */
/* Note: The Stream Command cannot be used on Cruiser because the */
/* wildcard character support was removed. */
/* */
/* (stream(db_full_path || 'SQL*.INX','c','query exist') \= '') ) | , */
/* */
'tarfqry ' db_full_path || 'SQL*.INX'
if ( single_tab = 'NO' & ,
(rc == 0) ) | ,
( single_tab = 'YES' & ,
(stream(indname,'c','query exist') \= '') ) then
do
'rxqueue /clear' /* clear queue */
if single_tab = 'YES' then
/* Push the index filename to be inspected on queue */
push indname
else
/* Check each .INX file in the database directory */
'dir/f ' db_full_path||'SQL*.INX | rxqueue /fifo'
do queued()
pull indname
/* Display progress message */
dsp_rc = charout(,prctxt || indname)
call ficlo 'REPORT' /* close the report file */
'tarchx ' indname rptname
tarchx_rc = rc
/* Display progress completion message for file */
if tarchx_rc = 0 then /* No errors found */
dsp_rc = charout(,goodtxt || cr_lf)
else /* Errors found */
dsp_rc = charout(,errtxt || cr_lf)
call filop 'REPORT' /* open the report file */
call handle_error tarchx_rc
end
end
/*********************************************
Log the Usable Database Index Inspection Phase End Heading
*********************************************/
call putout ' '
call putout chxend || time('L')
call putout ' '
call putout dashline
end /* If Usable Database Inspection decision is Yes */
/*********************************************
Index ReBuild Phase
*********************************************/
/* Check to see if any Error Index Files (.EIX) still exist */
/* */
/* Note: The Stream Command cannot be used on Cruiser because the */
/* wildcard character support was removed. */
/* */
/* if stream(db_full_path || 'SQL*.EIX','c','query exist') \= '' then */
'tarfqry ' db_full_path || 'SQL*.EIX'
if ((rc == 0) & (bias \= 'NSPEC')) then
do
/*********************************************
Log the ReBuild Index Phase Start Heading
*********************************************/
say cr_lf || rbxbeg
call putout ' '
call putout rbxbeg || time('L')
call putout ' '
/*********************************************
Start Using the Database in Exclusive Mode
*********************************************/
call sqldbs 'START USING DATABASE ' dbname ' IN EXCLUSIVE MODE'
if sqlca.sqlcode \= 0 then
call sqlxit
start_using = 'YES'
'rxqueue /clear' /* clear queue */
/* Queue each .EIX file in the database directory */
'dir/f ' db_full_path||'SQL*.EIX | rxqueue /fifo'
do queued()
pull eixname
/* Display progress message */
dsp_rc = charout(,prctxt || eixname)
/* Create the corresponding table filename */
eixdrv = FILESPEC("drive", eixname) /* Drive of the Error Index File */
eixpath = FILESPEC("path", eixname) /* Path of the Error Index File */
tmpfn = FILESPEC("name", eixname) /* Fname/Ext of Error Index File */
fname = eixdrv || eixpath || substr(tmpfn, 1, pos('.', tmpfn)) || 'DAT'
/* Get the Table Qualifier and Name */
call querytb
/* Issue a Select Stmt on the Table to ReBuild its Index(es) */
stmt3 = "SELECT COUNT(*) FROM " || full_tname
open_cursor = 'NO' /* open cursor succeed flag */
call SQLEXEC 'PREPARE s3 FROM :stmt3'
if sqlca.sqlcode = 0 then
do
call SQLEXEC 'DECLARE c3 CURSOR FOR s3'
if sqlca.sqlcode = 0 then
do
call SQLEXEC 'Open c3'
if sqlca.sqlcode = 0 then
do
call SQLEXEC 'FETCH c3 INTO :tmpcnt'
open_cursor = 'YES'
end
end
end
if open_cursor = 'YES' then
do
call SQLEXEC 'CLOSE c3'
end
/* Display the completion progress message */
dsp_rc = charout(,cmptxt || cr_lf)
end /* End of loop for ReBuilding Error Index Files */
/*********************************************
Issue STOP USING
*********************************************/
call sqldbs 'STOP USING DATABASE '
if sqlca.sqlcode \= 0 then
call sqlxit
start_using = 'NO'
/*********************************************
Log the ReBuild Index Phase End Heading
*********************************************/
call putout ' '
call putout rbxend || time('L')
call putout ' '
call putout dashline
end
/*********************************************
Successful Program Completion
*********************************************/
result = global_return
call putout ' '
if cat_flag = 'YES' then /* if syscatalog damaged, put out msg. */
call putout TAR0014N
select
when global_return = 0 then do
say TAR0000I
call putout TAR0000I
end
when global_return = 2 then do
say TAR0002I
call putout TAR0002I
end
when global_return = 4 then do
say TAR0004I
call putout TAR0004I
end
when global_return = 6 then do
say TAR0006I
call putout TAR0006I
end
when global_return = -12 then do
say TAR0012N
call putout TAR0012N
end
otherwise
end
signal finish
/*********************************************
PROGRAM EXITS
*********************************************/
/*********************************************
Final Program Clean-Up
*********************************************/
finish:
/* Stop Using the Database */
if start_using = 'YES' then
call sqldbs 'STOP USING DATABASE'
/* Stop DbMgr if started in this program */
if dbm_already_started = 'NO' then
call SQLDBS 'STOP DATABASE MANAGER'
/* Close the SYSBOOT File */
if boot_open = 'open' then
call ficlo 'BOOT' 'IGNORE'
/* Close the Database Configuration File */
if con_open = 'open' then
call ficlo 'CONFIG' 'IGNORE'
/* Close the Input Report File */
if rpt_open = 'open' then
call ficlo 'REPORT' 'IGNORE'
/* Close the DEP File */
if dep_open = 'open' then
call ficlo 'DEP' 'IGNORE'
/* ********************** */
/* TaRRR Exit Routine */
/* ********************** */
xit:
result = global_return /* Set the return code */
exit result /* Exit the program */
/* Pass return code */
/* **************************** */
/* TaRRR Error Exit Routine */
/* **************************** */
errxit:
parse arg msg_text
result = global_return
say msg_text
if (msg_text \= TAR0062N) & (msg_text \= TAR0064N) & (msg_text \= TAR0066N),
& (msg_text \= TAR0002N) & (msg_text \= TAR0006N) then
do
rc = lineout(rptname, ' ')
if rc \= 0 then say TAR0006N
rc = lineout(rptname, msg_text)
if rc \= 0 then say TAR0006N
end
/* Complete the Tool Cleanup */
signal finish
return
/* ************************************ */
/* SQL (Database Manager) Error Exit */
/* Dump error message on screen */
/* ************************************ */
sqlsit:
result = sqlca.sqlcode
/* Get the formatted SQL message */
call SQLDBS 'GET MESSAGE INTO :sql_msg LINEWIDTH 70'
if result = 0 then
do
/* Formatting successful - Display formatted message */
say sql_msg
end
else
do
/* Formatting unsuccessful - Display unformatted message */
say SQLMSG
end
/* Complete the Tool Cleanup */
signal finish
return
/*********************************************
SQL (Database Manager) Error Exit
Dump error message on report & on screen
*********************************************/
sqlxit:
result = sqlca.sqlcode
/* Get the formatted SQL message */
call SQLDBS 'GET MESSAGE INTO :sql_msg LINEWIDTH 70'
if result = 0 then
do
/* Formatting successful - Display formatted message */
say sql_msg
call putout sql_msg
end
else
do
/* Formatting unsuccessful - Display unformatted message */
say SQLMSG
call putout SQLMSG
end
/* Complete the Tool Cleanup */
signal finish
return
/*********************************************
SQL (Database Manager) Error Dump
*********************************************/
sqldump:
/* Get the formatted SQL message */
call SQLDBS 'GET MESSAGE INTO :sql_msg LINEWIDTH 70'
if result = 0 then
do
/* Formatting successful - Display formatted message */
call putout sql_msg
end
else
do
/* Formatting unsuccessful - Display unformatted message */
call putout SQLMSG
end
return
/*********************************************
SUBROUTINES
*********************************************/
/******************************************************************
* SUBROUTINE: PUTOUT *
* *
* DESCRIPTIVE NAME: write the input message into report *
* *
* DESCRIPTION: This routine will write the message into the *
* report, if not successful, the TaRRR will exit *
* with report I/O error. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
putout:
parse arg final_msg
rc = lineout(rptname,final_msg)
if rc \= 0 then
do
global_return = -6
call errxit TAR0006N
end
return
/******************************************************************
* SUBROUTINE: CHKARGS *
* *
* DESCRIPTIVE NAME: Check the Program Input Arguments *
* *
* DESCRIPTION: This routine checks the validity of the input *
* arguments for the program. If any arguments *
* are not specified, then the user is prompted to *
* type the required argument. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
chkargs:
/* Verify that the database name (and not an option parameter) was
specified first in the command; if not, reprompt for the
database name */
if substr(dbname, 1, 1) = '/' then
dbname = ''
if dbname = '' then /* Prompt for the Database name if not input */
do
'cls'
say dbname_text
pull dbname
end
if rptname = '' then /* Prompt for the Report Filename if not input */
do
say rptname_text
pull rptname
end
/*********************************************
Validate the Report Filename
*********************************************/
/* Terminate if report filename does not have a filename */
if FILESPEC("name", rptname) = '' then
do
global_return = -62
call errxit TAR0062N
end
/* Terminate if report filename with SQL or extension with DEP or DRR */
if substr(rptname,1,3) = 'SQL' | substr(reverse(rptname),1,4) = 'PED.',
| substr(reverse(rptname),1,4) = 'RRD.' then
do
global_return = -66
call errxit TAR0066N
end
/*********************************************
Open the Report File
*********************************************/
call filop 'REPORT'
/*********************************************
Determine the full-qualified path of the
database subdirectory.
*********************************************/
db_drive = '' /* drive of the database name */
db_subdir = '' /* subdirectory of the database name */
/* open system database directory */
inputs = 'OPEN DATABASE DIRECTORY ON 0 USING :db_dir'
call SQLDBS inputs
if (sqlca.sqlcode \= 0) then
call sqlxit
/* find the drive of the database */
do count = 1 to db_dir.2
inputs = 'GET DATABASE DIRECTORY ENTRY :db_dir.1'
call SQLDBS inputs
if (sqlca.sqlcode \= 0) then
call sqlxit
if sqldinfo.1 = dbname then
do
db_drive = sqldinfo.3
leave
end
end /* end do */
/* close the database directory */
inputs = 'CLOSE DATABASE DIRECTORY :db_dir.1'
call SQLDBS inputs
if (sqlca.sqlcode \= 0) then
call sqlxit
/* if the database name is not found in the database system directory */
if db_drive = '' then
do
global_return = -32
call errxit TAR0032N
end
db_drive = strip(db_drive,'t',':') /* strip out the : of the drive */
/* open volume database directory */
inputs = 'OPEN DATABASE DIRECTORY ON ' || db_drive || ' USING :db_dir'
call SQLDBS inputs
if (sqlca.sqlcode \= 0) then
call sqlxit
/* find the subdirectory of the database */
do count = 1 to db_dir.2
inputs = 'GET DATABASE DIRECTORY ENTRY :db_dir.1'
call SQLDBS inputs
if (sqlca.sqlcode \= 0) then
call sqlxit
if sqldinfo.1 = dbname then
do
db_subdir = sqldinfo.4
leave
end
end /* end do */
/* close the database directory */
inputs = 'CLOSE DATABASE DIRECTORY :db_dir.1'
call SQLDBS inputs
/* if the database name is not found in the database directory */
if db_subdir = '' then
do
global_return = -32
call errxit TAR0032N
end
else
/* get the path of the database */
db_full_path = db_drive || ':\' || db_subdir || '\'
/*********************************************
Get the Repair Bias option set correctly
*********************************************/
/* If Repair Bias not specified on */
/* command line, use default NSPEC */
if bias = '' then
bias = 'NEW'
/* If invalid Repair Bias specified */
/* Display general help error screen */
if bias \= 'NEW' & bias \= 'OLD' & bias \= 'NSPEC' & bias \= 'NSPECX' then
do
global_return = 80 /* Return a 80, invalid bias */
call general_help /* Display TaRRR syntax. */
signal xit /* End the program, invalid bias */
end
/*********************************************
Get the Automatic ReOrg option set correctly
*********************************************/
/* Set option to require prompting if specified incorrectly */
if reorg_opt \= 'YES' & reorg_opt \= 'NO' then
reorg_opt = ''
/*********************************************
Get the Automatic Usable Database Inspection
option set correctly
*********************************************/
/* Set option to require prompting if specified incorrectly */
if nspec_opt \= 'YES' & nspec_opt \= 'NO' then
nspec_opt = ''
/*********************************************
Get the Single Table and Single Page
options set correctly
*********************************************/
/* Check for single input table name */
if fname \= '' then
single_tab = 'YES' /* Single Table Repair/Inspection */
else /* Multiple Table Repair/Inspection */
fname = 'DUMMY' /* Set a dummy filename to prevent REXX error */
/* set the single_page option to YES, if single page option is chosen */
if inpage \= '' & single_tab = 'YES' then
single_page = 'YES'
/*********************************************
Get the Force Option set correctly
Note: The Force Option determines whether
or not TaRRR will detect the potential
Double Allocation problem.
/F:YES means that TaRRR will not detect
the Double Allocation problem and repair
will continue regardless of its existence.
/F:NO means that TaRRR will detect the
Double Allocation problem and repair will
terminate when it is detected.
Note: The Force Option is an undocumented option.
Its use should only be exercised by folks
willing to take the risk of repairing a
table even when there is a potential
file system allocation problem.
*********************************************/
if force_opt \= 'YES' then
force_opt = 'NO'
/*********************************************
Validate the Table Filename, if
Single Table option is chosen
*********************************************/
/* if single table option was specified, verify the specified filename */
if single_tab = 'YES' then
do
/*Verify that the specified filename is a valid database table file */
if substr(reverse(fname),1,4) \= 'TAD.' | length(fname) \= 24 then
do
global_return = -42
call errxit TAR0042N
end
/*Verify that the table file resides in the correct database subdir. */
if (db_full_path\=(FILESPEC("drive",fname)||FILESPEC("path",fname))) then
do
global_return = -42
call errxit TAR0042N
end
/*Verify that the specified filename does exist */
if stream(fname, 'C', 'query exist') = '' then
do
global_return = -44
call errxit TAR0044N
end
end
/*********************************************
Validate the Page Number, if
Single Page option is chosen
*********************************************/
/* if single page option was specified, verify the specified page number */
if single_page = 'YES' then
do
/* Verify that the page number is a whole number */
if datatype(inpage, 'W') \= 1 then
do
global_return = -52
call errxit TAR0052N
end
/* Check the page number is a valid page number */
if inpage < 0 then
do
global_return = -54
call errxit TAR0054N
end
/* Check the page number does exist in the table file. */
if stream(fname, 'C', 'query size') < ((inpage+1)*4096) then
do
global_return = -54
call errxit TAR0054N
end
end
return
/******************************************************************
* SUBROUTINE: FILOP *
* *
* DESCRIPTIVE NAME: Open the input file *
* *
* DESCRIPTION: This routine opens the input file. If the file is *
* the input Report File, then it also checks the *
* report file for an "End of File" character. *
* If the "End of File" character is found at the *
* end of the file, then the Write Position is *
* set such that any data appended to the file will *
* write over the "End of File" character. *
* *
* The "End of File" character can be inserted by *
* an ASCII Editor when the Report File is viewed *
* and saved. Then any data appended to the file *
* after the "End of File" code will not be *
* visible in the editor. *
* *
* INPUT: Type of file being opened (BOOT or CONFIG or REPORT *
* or DEP) *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
filop:
parse upper arg filtyp
/* Determine the type of file being opened */
select
/* The Report File is being opened */
when filtyp = 'REPORT' then do
if rpt_open = 'NO' then
do
/* Open the Input Report File */
rc = stream(rptname, 'c', 'open')
if (rc \= 'READY:') & (rc \= 'READY') then
do
global_return = -6
call errxit TAR0006N
end
else
do
rpt_open = 'YES'
/* Locate the last byte in the file */
eofpos = stream(rptname, 'c', 'query size')
/* Make sure the file is not empty before reading
the last byte */
if eofpos > 0 then
do
/* Position the Write Cursor on the last byte
of the file if it is an EOF control;
otherwise leave the Write Cursor positioned
after the last byte */
if charin(rptname, eofpos, 1) = x2c('1A') then
r = stream(rptname, 'c', 'seek -1')
end
end
end
end /* End of Report File Open */
/* The CONFIG File is being opened */
when filtyp = 'CONFIG' then do
if con_open = 'NO' then
do
/* Open the Database Configuration File */
rc = stream(conname, 'c', 'open')
if (rc \= 'READY:') & (rc \= 'READY') then
do
global_return = -16
call errxit TAR0016A || conname || TAR0016B
end
else
con_open = 'YES'
end
end /* End of Database Configuration File Open */
/* The BOOT File is being opened */
when filtyp = 'BOOT' then do
if boot_open = 'NO' then
do
/* Open the Database BOOT File */
rc = stream(bootname, 'c', 'open')
if (rc \= 'READY:') & (rc \= 'READY') then
do
global_return = -16
call errxit TAR0016A || bootname || TAR0016B
end
else
boot_open = 'YES'
end
end /* End of Database BOOT File Open */
/* The DEP File is being opened */
when filtyp = 'DEP' then do
if dep_open = 'NO' then
do
/* Open the Input .DEP File */
rc = stream(depname, 'c', 'open')
if (rc \= 'READY:') & (rc \= 'READY') then
do
global_return = -8
call errxit TAR0008N
end
else
dep_open = 'YES'
end
end /* End of DEP File Open */
end /* End of Select */
return
/******************************************************************
* SUBROUTINE: FICLO *
* *
* DESCRIPTIVE NAME: Close the file *
* *
* DESCRIPTION: This routine closes the input file. It also *
* provides an option to ignore errors from the Close*
* *
* Ignoring errors will be used during the cleanup *
* at the conclusion of TaRRR. *
* *
* INPUT: Type of file being opened (BOOT or CONFIG or REPORT *
* or DEP) *
* *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
ficlo:
parse upper arg filtyp erropt
rc = 'READY:' /* Initialize the return code variable */
/* Determine the type of file being closed */
select
/* The Report File is being closed */
when filtyp = 'REPORT' then do
/* Close the Input Report File */
rc = stream(rptname, 'c', 'close')
if (erropt \= 'IGNORE') & (rc \= 'READY:') & (rc \= 'READY') then
do
global_return = -6
call errxit TAR0006N
end
else
rpt_open = 'NO'
end /* End of Report File Close */
/* The CONFIG File is being closed */
when filtyp = 'CONFIG' then do
/* Close the Database Configuration File */
rc = stream(conname, 'c', 'close')
if (erropt \= 'IGNORE') & (rc \= 'READY:') & (rc \= 'READY') then
do
global_return = -16
call errxit TAR0016A || conname || TAR0016B
end
else
con_open = 'NO'
end /* End of Database Configuration File Close */
/* The BOOT File is being closed */
when filtyp = 'BOOT' then do
/* Close the Database BOOT */
rc = stream(bootname, 'c', 'close')
if (erropt \= 'IGNORE') & (rc \= 'READY:') & (rc \= 'READY') then
do
global_return = -16
call errxit TAR0016A || bootname || TAR0016B
end
else
boot_open = 'NO'
end /* End of Database BOOT File Close */
/* The .DEP File is being closed */
when filtyp = 'DEP' then do
/* Close the .DEP File */
rc = stream(depname, 'c', 'close')
if (erropt \= 'IGNORE') & (rc \= 'READY:') & (rc \= 'READY') then
do
global_return = -8
call errxit TAR0008N
end
else
dep_open = 'NO'
end /* End of DEP File Close */
end /* End of Select */
return
/******************************************************************
* SUBROUTINE: RPTHDR *
* *
* DESCRIPTIVE NAME: Write the Report File Header *
* *
* DESCRIPTION: This routine writes the information that appears *
* at the beginning of the Report for a given *
* execution of TaRRR. *
* *
* Note: The Report File must already be opened. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
rpthdr:
/* Write space lines */
call putout ' '
call putout ' '
/* Write the Report Delimiter Lines */
call putout eqlines
call putout eqlines
call putout eqlines
call putout eqlines
/* Write space lines */
call putout ' '
call putout ' '
/* Write Title line */
ttline = title || date('N') || ' ' || time('C')
call putout ttline
call putout ' '
call putout ' '
/* write out the database name */
dbline = dbtext || dbname
call putout dbline
/* write out the database subdirectory */
dbsubline = dbsubtext || db_full_path
call putout dbsubline
call putout ' '
call putout ' '
/* Write out the Repair Bias option */
select
when bias = 'OLD' then do
bopttxt = biatxt || biasold
end
when bias = 'NEW' then do
bopttxt = biatxt || biasnew
end
when bias = 'NSPEC' then do
bopttxt = biatxt || biasnsp
end
when bias = 'NSPECX' then do
bopttxt = biatxt || biasnspx
end
end
call putout bopttxt
/* Write out Force Option text if specified */
if force_opt = 'YES' then
do
call putout ' '
call putout ' '
call putout frctxt
end
call putout ' '
call putout ' '
call putout dashline
call putout dashline
call putout ' '
return
/******************************************************************
* SUBROUTINE: QUERYTB *
* *
* DESCRIPTIVE NAME: Query Table Name from file token *
* *
* DESCRIPTION: This routine get the full qualifier table name *
* from SYSTABLES by using FID of table data file *
* and store in the full_tname *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
querytb:
/*********************************************
Determine the Table Name for the Damaged Table File
*********************************************/
tmpfn = FILESPEC("name", fname) /* Filename of Table File */
tab_token = strip(substr(tmpfn, 4, 5),'L',0) /* get file token of table */
stmt2 = "SELECT CREATOR, NAME FROM SYSIBM.SYSTABLES ",
"WHERE FID=" || tab_token
tqual = '' /* initialize creator */
tname = '' /* initialize table name */
open_cursor = 'NO' /* open cursor succeed flag */
call SQLEXEC 'PREPARE s2 FROM :stmt2'
if sqlca.sqlcode = 0 then
do
call SQLEXEC 'DECLARE c2 CURSOR FOR s2'
if sqlca.sqlcode = 0 then
do
call SQLEXEC 'Open c2'
if sqlca.sqlcode = 0 then
do
call SQLEXEC 'FETCH c2 INTO :tqual, :tname'
open_cursor = 'YES'
end
end
end
/*********************************************
Create the Full Table Name with Qualifier
*********************************************/
if sqlca.sqlcode \= 0 then
do
/* Note: Because the "Inspection Only" mode may be inspecting a */
/* database that cannot be connected to, the error message */
/* from the above Select is being removed so that it does */
/* not get repeated over and over. */
/* If the table name ends up being "..." on the screen, then */
/* that is a good indication that a Select error occurred */
/* and probably a Start Using error occurred prior to that. */
/* Handle the special case of SYSBOOT */
if tmpfn = 'SQL00001.DAT' then
full_tname = 'SYSIBM.SYSBOOT'
else /* the table name is unknown */
full_tname = '...'
end
else
full_tname = strip(tqual) || '.' || strip(tname)
if open_cursor = 'YES' then
do
call SQLEXEC 'CLOSE c2'
end /* Close cursor when Open cursor succeed */
return
/******************************************************************
* SUBROUTINE: RETAIN_ROW *
* *
* DESCRIPTIVE NAME: Dump the retain_row. *
* *
* DESCRIPTION: This routine will dump the retained rows when *
* repair option biased OLD. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
retain_row:
call filop 'DEP' /* Open DEP file */
no_page = c2d(reverse(charin(depname, 1, 4))) /* number of damaged pages */
if no_page < 61 then
do
do i = 1 to no_page
damage_page = c2d(reverse(charin(depname, (i*4)+1, 4)))
call putout pgtext || damage_page
call ficlo 'REPORT' /* Close Report File */
'tarddat ' fname rptname '-p ' damage_page damage_page
call filop 'REPORT' /* Open Report File */
end
end
call ficlo 'DEP' /* Close DEP file */
return
/******************************************************************
* SUBROUTINE: VER_CAT *
* *
* DESCRIPTIVE NAME: Verify if the table name is one of the *
* System Catalogs. *
* *
* DESCRIPTION: This routine will verify the table name to see *
* if it is one of the System Catalogs. If it is, *
* then cat_flag is set to 'YES'. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
ver_cat:
if cat_flag = 'NO' then
do
tmpcat_fname = strip(substr(FILESPEC("name",fname),4),'L','0')
do i=1 to 14 /* for all the syscatalog */
if (catalog.i||'.DAT') = tmpcat_fname then
cat_flag = 'YES'
end
if tmpcat_fname = '1.DAT' then /* if this is SYSBOOT */
cat_flag = 'YES'
end /* verify only when no syscatalog damaged so far */
return
/******************************************************************
* SUBROUTINE: CATREAD *
* *
* DESCRIPTIVE NAME: Read SYSCATALOG from SYSBOOT file *
* *
* DESCRIPTION: This routine reads the FID of the System *
* Catalogs from the SYSBOOT file and stores those *
* File IDs into a compound variable "catalog" for *
* future comparison. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
catread:
bootname = db_full_path || 'SQL00001.DAT'
call filop 'BOOT'
boot_off = c2d(reverse(charin(bootname, 79, 2))) /* slot 4 */
bootstart = 71 + boot_off /* boot record offset */
/* for more information about sysboot, read sqlrlbot.c */
/* get all 14 FID of syscatalog */
do i=1 to 14
catalog.i = c2d(reverse(charin(bootname, bootstart+16+(i-1)*3, 2)))
end
call ficlo 'BOOT'
return
/******************************************************************
* SUBROUTINE: CFGREAD *
* *
* DESCRIPTIVE NAME: Read Info from the Database Configuration *
* *
* DESCRIPTION: This routine reads the signature and the release *
* from the database configuration file. The *
* database signature is used to validate each page *
* in the table(s). The release number is used to *
* determine whether or not the database is a SBCS *
* or DBCS database. *
* This routine also checks the external indicators. *
* If the Copy Protect, Enable Log Retain, Enable *
* Log Exit, or Automatic Restart are set, then *
* they will be reset. The most important of these *
* is the resetting of Enable Log Retain to prevent *
* a user from trying to do Roll-Forward Recovery *
* on a repaired database. The others are more for *
* insurance in the repair environment. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
cfgread:
/* Open the database configuration file */
conname = db_full_path || 'SQLDBCON'
call filop 'CONFIG'
/* Define the offsets and lengths for the necessary fields in the config */
dbc_chksumo = 1 /* Checksum field offset */
dbc_chksuml = 4 /* length */
dbc_rel_off = 17 /* Offset of database release field */
dbc_rel_len = 2 /* Length of database release field */
um_seed_off = 45 /* Offset of unmasked database seed */
um_seed_len = 4 /* Length of unmasked database seed */
dbc_exflgo = 593 /* External Indicator/Status Flag offset*/
dbc_exflgl = 2 /* length */
/* Retrieve the database release */
db_release = c2x(reverse(charin(conname, dbc_rel_off, dbc_rel_len)))
/* Retrieve the database signature */
db_signature = c2d(reverse(charin(conname, um_seed_off, um_seed_len)))
/* External Indicator/Status Flag */
dbc_exflg = c2x(reverse(charin(conname, dbc_exflgo, dbc_exflgl)))
/* Close the database configuration file */
call ficlo 'CONFIG'
/* Based on the Database Release, determine whether the database is an SBCS */
/* or DBCS database */
/* Note: The high nibble of the Release number is '0' for SBCS and */
/* 'D' for DBCS */
if bitand(x2c(db_release), 'F000'x) = 'D000'x then
do
char_set = 'D' /* DBCS Database */
/* Write out DBCS Database text to Report File */
call putout ' '
call putout ' '
call putout dbcstxt
call putout ' '
call putout ' '
call putout dashline
call putout dashline
call putout ' '
end
else
char_set = 'S' /* SBCS Database */
/* Check the status of the External Status Flag */
/* If any of the following flags are set, */
/* then they are reset prior to continuing the repair. */
/* Get the External Indicator Flag in Character Form */
out_exflg = x2c(dbc_exflg)
/* Determine state of the following External Indicators: Copy Protect */
/* Enable Log Retain */
/* Enable Log Exit */
/* Automate Restart */
/* If one of these indicators is set, then they will be reset in order to */
/* regulate the repair environment by removing potential obstacles to a */
/* successful repair and subsequent use of the repaired database. */
/* Note: This only needs to be done during a Repair Mode and not during */
/* the Inspection Only Mode. */
if ((bias \= 'NSPEC') & (bias \= 'NSPECX') & ,
(bitand(out_exflg, '000F'x) \= '0000'x)) then
do
/* Display the Warning about the Change to the Database Configuration */
'cls'
say dbcfg_text
'pause'
/* Open the Database Configuration File again */
call filop 'CONFIG'
/* Reset the following External Indicators: Copy Protect */
/* Enable Log Retain */
/* Enable Log Exit */
/* Automatic Restart */
out_exflg = bitand(out_exflg, 'FFF0'x)
dbc_exflg = c2x(out_exflg)
cfg_rc = charout(conname, reverse(out_exflg), dbc_exflgo)
/* Re-calculate the Checksum value */
/* Initialize the cursor position to the 5th character */
/* Note: The first four characters are the CheckSum value */
cursor_pos = 5
/* Initialize the checksum value */
checksum = 0
/* Loop to read each character in the file */
do cursor_pos=5 to stream(conname, 'c', 'query size')
/* Read the next character */
char_value = charin(conname, cursor_pos, 1)
/* Add the character to the checksum value */
checksum = checksum + c2d(char_value)
end
/* Set the Write Cursor to the beginning of the Database Configuration file */
cfg_rc = stream(conname, 'c', 'seek =1')
/* Set the CheckSum field in the Database Configuration to calculated value */
dbc_chksum = checksum
cfg_rc = charout(conname, reverse(substr(d2c(dbc_chksum, 4), 3, 2)) || ,
reverse(substr(d2c(dbc_chksum, 4), 1, 2)) ,
, dbc_chksumo)
/* Close the database configuration file */
call ficlo 'CONFIG'
/* Write out Config Indicator text to Report File */
call putout ' '
call putout ' '
call putout cfgtxt
call putout ' '
call putout ' '
call putout dashline
call putout dashline
call putout ' '
end
return
/******************************************************************
* SUBROUTINE: INSPEC *
* *
* DESCRIPTIVE NAME: Initiate the Inspection/Repair Phase *
* *
* DESCRIPTION: This routine calls TARNSPEC to initiate the *
* Inspection/Repair Phase of TaRRR. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
inspec:
/*********************************************
Get the option flag
*********************************************/
fndrv = FILESPEC("drive", fname) /* Drive of the Table File Name */
fnpath = FILESPEC("path", fname) /* Path of the Table File Name */
tmpfn = FILESPEC("name", fname) /* Filename/Ext of Table File Name */
indname = fndrv || fnpath || substr(tmpfn, 1, pos('.', tmpfn)) || 'INX'
option_flag = 0 /* default to no index, biased NEW */
/* if index exist, then set 1st-bit to 1 */
if stream(indname, 'C', 'query exist') \= '' then
option_flag = c2d(bitor(d2c(option_flag), '01'x))
/* if option biased OLD, then set 2nd-bit to 1 */
if bias = 'OLD' then
option_flag = c2d(bitor(d2c(option_flag), '02'x))
/* Set up the Force Opt for the Inspection Program */
if force_opt = 'YES' then
option_flag = c2d(bitor(d2c(option_flag), '04'x))
/* Set up the DBCS Opt for the Inspection Program */
if char_set = 'D' then
option_flag = c2d(bitor(d2c(option_flag), '08'x))
call ficlo 'REPORT' /* close the report file */
if single_page = 'NO' then /* call the inspection program */
'tarnspec ' fname rptname db_signature option_flag
else
'tarnspec ' fname rptname db_signature option_flag '/P:'inpage
inspec_rc = rc /* save return code of the inspection */
/* Display progress completion message for file */
select
when inspec_rc = 0 then /* No errors found */
dsp_rc = charout(,goodtxt || cr_lf)
when inspec_rc = 2 then /* No further repair necessary */
dsp_rc = charout(,reptxt || cr_lf)
otherwise /* Errors or ReConstruction required */
dsp_rc = charout(,errtxt || cr_lf)
end
call filop 'REPORT' /* Open the Report File */
/* Handle return codes from TARNSPEC */
/* Note: The non-fatal return codes "Errors found and Page does not */
/* Require ReConstruction (2)" and "Page Requires ReConstruction */
/* (4)" should not be preserved in global_return so handle_error */
/* will not be called in that case. These return codes are */
/* essentially ignored at this point. The existence of .DEP files*/
/* will be used to determine the necessity for ReConstruction. */
if inspec_rc > 10 then
call handle_error inspec_rc /* handle error return */
if inspec_rc \= 0 then /* verify if a syscatalog or not */
call ver_cat
return
/******************************************************************
* SUBROUTINE: RECON *
* *
* DESCRIPTIVE NAME: Initiate the ReConstruction Phase *
* *
* DESCRIPTION: This routine calls TARRECON to initiate the *
* ReConstruction Phase of Table Repair. It will *
* resolve any UnMatched Pointer Records in the *
* table as well as generate the Lost Row Report *
* thru the use of keys in a unique index. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
recon:
/*********************************************
Determine the Internal Index ID of the
smallest colcount of the unique index
*********************************************/
tmpfn = FILESPEC("name", fname) /* Filename of Table File */
tab_token = strip(substr(tmpfn, 4, 5),'L',0) /* get file token of table */
stmt1 = "SELECT IID, COLCOUNT, NAME, CREATOR, COLNAMES FROM ",
"SYSIBM.SYSINDEXES WHERE TBNAME=",
"ANY (SELECT NAME FROM SYSIBM.SYSTABLES WHERE FID="||tab_token|| ")",
"AND TBCREATOR = ANY (SELECT CREATOR FROM SYSIBM.SYSTABLES WHERE FID=",
||tab_token|| ") AND (UNIQUERULE = 'P' OR UNIQUERULE = 'U')",
" ORDER BY COLCOUNT"
/* Initialize the index related variables */
iid = 0 /* Internal Index ID */
call SQLEXEC 'PREPARE s1 FROM :stmt1'
if (sqlca.sqlcode = 0) then
do
call SQLEXEC 'DECLARE c1 CURSOR FOR s1'
if (sqlca.sqlcode = 0) then
do
call SQLEXEC 'Open c1'
if (sqlca.sqlcode = 0) then
do
call SQLEXEC 'FETCH c1 INTO :iid, :colcount, :name, :creator, :colnames'
call SQLEXEC 'CLOSE c1'
end /* open cursor successful */
end /* declare successful */
end /* Prepare successful */
/* Initialize to non-null string if no unique index found */
if iid = 0 then
colnames = '+'
call querytb
call putout ' '
call putout tbname||full_tname /* table name logged */
call putout tbtext||fname /* table file name logged */
if iid \= 0 then /* index name logged */
call putout indtext||strip(creator)||'.'||strip(name)
if bias = 'OLD' then /* Dump Retained Row Report */
call retain_row
/* Set options for ReConstruction Program */
option_flag = 0 /* default to No Force option */
/* Set up the Force Opt for the Inspection Program */
if force_opt = 'YES' then
option_flag = c2d(bitor(d2c(option_flag), '01'x))
call ficlo 'REPORT' /* close the report file */
/* Initiate the ReConstruction phase */
'cvp tarrecon ' fname iid colnames rptname option_flag
recon_rc = rc /* return code of reconstruct. */
/* Display progress completion message for file */
select
when recon_rc = 0 then /* No Rows Lost */
dsp_rc = charout(,rcntxt || cr_lf)
when recon_rc > 10 then /* Errors encountered */
dsp_rc = charout(,errtxt || cr_lf)
otherwise /* Rows Lost */
dsp_rc = charout(,lsttxt || cr_lf)
end
call filop 'REPORT' /* Open the Report File */
call handle_error recon_rc /* handle error return */
drrname = substr(tmpfn,1,pos('.',tmpfn)) || 'DRR'
if (recon_rc = 2) | (recon_rc = 0) then /* if recon suceeds, rename .DEP*/
'rename ' depname drrname
else
if recon_rc = 10 then /* if table lost completely */
do
if (full_tname \= '...') then
do
call dummy_desc /* Create dummy Table Descr */
drop_table = 'DROP TABLE '|| full_tname
call SQLEXEC 'EXECUTE IMMEDIATE :drop_table'
if (sqlca.sqlcode \= 0) then
call sqldump
/* Commit the Drop Table */
call SQLEXEC 'COMMIT'
if (sqlca.sqlcode \= 0) then
call sqldump
end
else
'erase ' fname /* table not in syscatalog */
'erase ' depname /* erase .DEP file */
end
return
/******************************************************************
* SUBROUTINE: DUMMY_DESC *
* *
* DESCRIPTIVE NAME: Create the Dummy Descriptor Record *
* *
* DESCRIPTION: This routine gets control when an entire table *
* has been lost during repair. Because of the *
* inability of Database Manager to drop a table *
* whose Table Descriptor Record has been lost *
* and unrecovered, this routine will create a *
* dummy table descriptor record in the slot *
* directory in order to proceed with dropping the *
* table. *
* *
* In addition, the Slot Count of the page is *
* truncated to 4 since the dummy table descriptor *
* record is written in the slot directory itself. *
* This becomes important when the index has been *
* renamed previously such that Database Manager *
* will attempt to rebuild the index during the *
* Drop Table request. *
* *
* Note: The table has already been truncated to a *
* single page during ReConstruction. Again *
* this must be done because Database Mgr *
* attempts to rebuild a renamed index *
* during the Drop Table request. No! This *
* does not make sense. *
* *
* If the table cannot be dropped after this, there *
* is no hope. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
dummy_desc:
/* Open the table file */
rc = stream(fname, 'c', 'open')
if (rc = 'READY:') | (rc = 'READY') then
do
/* Define offset to Table Descriptor Record slot in Slot Directory */
bpshdr_sz = 50 /* Size of BPS Header */
dfhdr_sz = 20 /* Size of Data File Header */
/* Calculate offset to Slot Count in Data File Header */
dfhslot_off = bpshdr_sz + 1
/* Calculate offset to Table Desc Rec slot in Slot Directory */
dum_rec_off = bpshdr_sz + dfhdr_sz + (3*2) + 1
/* Truncate the Slot Directory to 4 in Page 0 */
new_slotcnt = 4
rc = charout(fname, reverse(d2c(new_slotcnt,2)), dfhslot_off)
/* Create dummy record header */
dum_rec = '080000000400'x
/* Write out dummy record header */
rc = charout(fname, dum_rec, dum_rec_off)
/* Close the table file to be dropped */
rc = stream(fname, 'c', 'close')
end
return
/******************************************************************
* SUBROUTINE: HANDLE_ERROR *
* *
* DESCRIPTIVE NAME: handle the return code *
* *
* DESCRIPTION: This routine will handle the error code and decide*
* what to do after that. It will also set the final *
* return code of the TaRRR. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
handle_error:
parse arg rcode
if rcode > 10 then
do
rcode = rcode - 255
global_return = rcode /* rcode = -12 handled here */
select
when rcode = -2 then call errxit TAR0002N
when rcode = -4 then call errxit TAR0004N
when rcode = -6 then call errxit TAR0006N
when rcode = -8 then call errxit TAR0008N
when rcode = -10 then call errxit TAR0010N
when rcode = -18 then call errxit TAR0018N
otherwise
end /* end of select rcode */
end /* return rcode < 0 */
else
do
/* Convert "Entire Table Lost" to the external "Data Rows Lost" rc */
if rcode = 10 then rcode = 2
/* Preserve the Non-Fatal Return Code */
if (global_return = 0) & (rcode > 0) then
global_return = rcode
else
do
/* Determine if "Rows Lost" returned from ReConstruction and
"Known Problems Still Exist" returned from the Usable
Database Inspection */
if (global_return = 2) & (rcode = 4) then
/* Return the combined "Rows Lost"/"Known Problems" rc */
global_return = 6
end
end
return
/******************************************************************
* SUBROUTINE: GENERAL_HELP *
* *
* DESCRIPTIVE NAME: TaRRR General Help *
* *
* DESCRIPTION: This routine displays the Help panels for the *
* TaRRR Tool. This routine receives control *
* when the first input parameter is a "?". A *
* brief description of the TaRRR and its *
* syntax is included in the Help panels. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
general_help:
/* Display help panel */
say " "
say ,
" ┌────────────────────────────────────────────────────────────┐ "
say ,
" │ ┌────────────────────────────────────────┐ │ "
say ,
" │ │ ***** T a R R R ***** │ │ "
say ,
" │ │ A Utility for │ │ "
say ,
" │ │ Table Repair/Recover/ReConstruction │ │ "
say ,
" │ └────────────────────────────────────────┘ │ "
say ,
" │ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ │ "
say ,
" │ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ │ "
say ,
" │ ▀▀▀▀ ▀▀▀ ▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ │ "
say ,
" │ ▀▀▀▀ ▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀ ▀▀▀▀▀▀ │ "
say ,
" │ ▀▀▀▀ ▀▀▀▀▀▀▀▀▀ ▀▀▀ ▀▀▀▀▀ ▀▀▀ │ "
say ,
" │ ▀▀▀▀ ▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀▀ ▀▀▀ │ "
say ,
" │ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀ ▀ ▀▀▀▀ │ "
say ,
" │ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀▀▀ │ "
say ,
" └────────────────────────────────────────────────────────────┘ "
say ,
" ╔══════════════════════════════════════════════════════════════════════╗ "
say ,
" ║ The TaRRR Tool is a utility for the Repair, Recovery and ║ "
say ,
" ║ ReConstruction of damaged tables in a database. It provides the ║ "
say ,
" ║ repair of damaged page fields, the retaining of existing records ║ "
say ,
" ║ or the recovery from the Write-Ahead Log, and the generation of ║ "
say ,
" ║ information in the report for page reconstruction. The purpose of ║ "
say ,
" ║ this tool is to make the database and its tables usable if possible.║ "
say ,
" ╚══════════════════════════════════════════════════════════════════════╝ "
say " "
'pause'
say " "
say ,
" Syntax: TaRRR [dbname] [/B:{OLD | NEW | NSPEC | NSPECX}]"
say ,
" [/T:fname] [/P:page] "
say ,
" [/R:[[path]rptname[.ext]]] "
say ,
" [/O:{YES|NO}] [/I:{YES|NO}] "
say " "
say " where: "
say ,
" [dbname] is the alias name of the database containing the "
say ,
" damaged table(s). "
say " "
say ,
" [/B:{OLD|NEW|NSPEC|NSPECX}] is the optional Repair Bias Option "
say ,
" keyword specification. "
say " "
say ,
" [/T:fname] is the optional fully-qualified OS/2 filename of the "
say ,
" damaged table. "
say ,
" [/P:page] is the optional damaged page number in the table file. "
say " "
say ,
" [/R:rptname] is the OS/2 filename of the Report File. "
say " "
say ,
" [/O:{YES|NO}] is the Automatic ReOrg Option keyword specification. "
say ,
" [/I:{YES|NO}] is the Automatic Usable Database Inspection keyword "
say ,
" specification. "
return