home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
tarv314.zip
/
EERESET.CMD
next >
Wrap
OS/2 REXX Batch file
|
1992-12-07
|
91KB
|
1,993 lines
/******************************************************************
* MODULE NAME: EERESET *
* *
* DESCRIPTIVE NAME: Reset the Log Control File *
* in EE 1.2, 1.3 level databases. *
* *
* LPP NAME: Standalone Tool *
* *
* DESCRIPTION: This routine provides a mechanism for resetting *
* or initializing the Log Control File to a state *
* in which it appears that the database no longer *
* needs recovery. *
* *
* Caution should be exercised in using this tool *
* because it will prevent any committed changes *
* which did not make it to media from being *
* recovered in the database. As a result, there *
* could be index and table mismatches and *
* referential integrity violations. *
* *
* DEPENDENCIES: *
* SYSTEM CONFIRUATION: *
* - OS/2 EE 1.2 and OS/2 EE 1.3 *
* *
* LANGUAGE INTERPRETER: *
* - OS/2 Rexx Interpreter *
* *
* PREREQUISTIES: None *
* *
* *
* RESTRICTIONS: None *
* *
* INPUT: Database name *
* Report File *
* *
* OUTPUT: Log Control File reset. *
* Usable database. *
* *
* *
* HOST LANGUAGE: OS/2 Rexx *
* *
* LAST CHANGE DATE: Version 1.4 09/29/91 *
* *
* *
******************************************************************/
parse upper arg dbname rptname
'@echo off'
TRACE OFF
numeric digits 15 /* Set precision for arithmetic operations */
dbpath = '' /* Initialize database path specification */
logpath = '' /* Initialize log path specification */
cr_lf = d2c(13) || d2c(10) /* Line End characters */
report_open = 'NO' /* Initialize Report Open Indicator */
/*********************************************
Check the Program Input Arguments
*********************************************/
if dbname = '?' then
do
call general_help
signal xit
end
else /* No Help requested, so check the input parameters */
call chkargs
'cls'
say ' '
say ,
" ╔══════════════════════════════════════════════════════════════════════╗ "
say ,
" ║ ** NOTICE ** NOTICE ** NOTICE ** NOTICE ** NOTICE ** ║ "
say ,
" ║ ║ "
say ,
" ║ THE LOG CONTROL FILE IS ABOUT TO BE RESET !! ║ "
say ,
" ║ ║ "
say ,
" ║ Caution: This should only be done as a very last resort. ║ "
say ,
" ║ It will prevent all committed changes in the ║ "
say ,
" ║ Write-Ahead Log from being applied to the database. ║ "
say ,
" ║ ║ "
say ,
" ║ ********** WARNING ===> DATA INTEGRIT MAY BE LOST ********** ║ "
say ,
" ║ ║ "
say ,
" ║ Would you like to Reset the Log Control File now? (y/n) ║ "
say ,
" ║ If so, type 'y' and press ENTER; ║ "
say ,
" ║ Otherwise, type 'n' and press ENTER. ║ "
say ,
" ╚══════════════════════════════════════════════════════════════════════╝ "
say " "
say " "
pull reset_decision
if reset_decision = 'Y' then
do
/*********************************************
Determine the Database Subdirectory
*********************************************/
say '....Scanning the Database Directory'
call getddir
if dbpath = '' then
call errxit 'The database was not found on the file system.'
/*********************************************
Construct the Database Configuration File
*********************************************/
dbcon_name = dbpath || 'SQLDBCON'
/*********************************************
Check Existence of Configuration File
*********************************************/
rc = stream(dbcon_name, 'c', 'query exist')
if rc = '' then
do
call errxit 'The Database Configuration File could not be found.'
end
/*********************************************
Open the Report File if specified
*********************************************/
if rptname \= '' then
do
rc = stream(rptname, 'c', 'open')
if (rc \= 'READY:') & (rc \= 'READY') then
do
call errxit 'The Report File could not be opened.'
end
report_open = 'YES' /* Report is now Open Indicator */
/*********************************************
Set the Write Cursor to Append to the Report File
*********************************************/
/* 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
/*********************************************
Write the Report File Header
*********************************************/
call rpthdr
end
/*********************************************
Open the Database Configuration File
*********************************************/
rc = stream(dbcon_name, 'c', 'open')
if (rc \= 'READY:') & (rc \= 'READY') then
do
call errxit 'The Database Configuration File could not be opened.'
end
/*********************************************
Find the Path to the Log File
*********************************************/
say '....Examining the Database Configuration'
call findlog
/*********************************************
Close the Database Configuration File
*********************************************/
rc = stream(dbcon_name, 'c', 'close')
/*********************************************
Construct Log Control File Name if Log Path Found
*********************************************/
if logpath = '' then
call errxit 'The Log Control File could not be found.'
else
/* Construct the Log Control File Name */
logctl_name = logpath || 'SQL00000.LOG'
/*********************************************
Open the Log Control File
*********************************************/
rc = stream(logctl_name, 'c', 'open')
if (rc \= 'READY:') & (rc \= 'READY') then
do
call errxit 'The Log File could not be opened.'
end
/*********************************************
Reset the Log Control File
*********************************************/
call reset
/*********************************************
Close the Log Control File
*********************************************/
rc = stream(logctl_name, 'c', 'close')
/*********************************************
Successful Program Completion
*********************************************/
say ' '
say 'The Reset Log Tool completed.'
signal finish
end
else /* User chose not to reset the Log Control File */
say 'Program terminated by user -- Log Control File not reset.'
/* ************************************************************************ */
/* ======================= PROGRAM EXITS ============================== */
/* ************************************************************************ */
/*********************************************
Final Program Clean-Up
*********************************************/
finish:
/*********************************************
Close the Report File if specified
*********************************************/
if report_open = 'YES' then
rc = stream(rptname, 'c', 'close')
xit:
/* Exit the program */
exit
/* ************************************************************************ */
/* ---------------------- FASTARRR Error Exit ------------------------- */
/* ************************************************************************ */
errxit:
parse arg msg_text
/* Display the Error Message */
say ' '
say msg_text
/* Complete the Tool Cleanup */
signal finish
return
/*********************************************
SQL (Database Manager) Error Exit
*********************************************/
sqlxit:
/* 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 ' '
say sql_msg
end
else
do
/* Formatting unsuccessful - Display unformatted message */
say ' '
say SQLMSG
end
/* Complete the Tool Cleanup */
signal finish
return
/* ************************************************************************ */
/* +++++++++++++++++++++++++ SUBROUTINES ++++++++++++++++++++++++++++++ */
/* ************************************************************************ */
/******************************************************************
* 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:
if dbname = '' then /* Prompt for the Database name if not input */
do
'cls'
say " "
say ,
" ╔══════════════════════════════════════════════════════════════════════╗ "
say ,
" ║ ║ "
say ,
" ║ Please type the input Database Name and press ENTER: ║ "
say ,
" ║ ║ "
say ,
" ╚══════════════════════════════════════════════════════════════════════╝ "
say " "
say " "
pull dbname
end
return
/******************************************************************
* SUBROUTINE: GETDDIR *
* *
* DESCRIPTIVE NAME: Get the Database Directory *
* *
* DESCRIPTION: This routine scans the System Database Directory *
* to determine the Drive containing the specified *
* database. If it finds the database on a local *
* volume, then it calls another routine to *
* scan the Volume Database Directory to determine *
* the subdirectory containing the database. *
* *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
getddir:
/*********************************************
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
call errxit 'Database Manager registration error'
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
call errxit 'Database Manager registration error'
end /* end if */
/*********************************************
Scan System Directory for Database Name
*********************************************/
call SQLDBS 'open database directory on 0 using :dhandle'
if sqlca.sqlcode < 0 then
signal sqlxit
do while sqlca.sqlcode = 0
call SQLDBS 'get database directory entry :dhandle.1'
if sqlca.sqlcode = 0 then
do
if SQLDINFO.1 = dbname then
do
db_drive = SQLDINFO.3
dbname = strip(dbname)
call scanvol
leave
end
end
end
call SQLDBS 'close database directory :dhandle.1'
return
/******************************************************************
* SUBROUTINE: SCANVOL *
* *
* DESCRIPTIVE NAME: Scan the Volume Database Directory *
* *
* DESCRIPTION: This routine scans the Volume Database Directory *
* to determine the Subdirectory containing the *
* specified database. *
* *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
******************************************************************/
scanvol:
/* Scan volume directory for name */
dbpath = ''
call SQLDBS 'open database directory on 'left(db_drive,1)' using :vhandle'
if sqlca.sqlcode = 0 then
do
do forever
call SQLDBS 'get database directory entry :vhandle.1'
if SQLCA.SQLCODE = 1014 then
do
say 'No entry found in volume directory for drive 'db_drive'...'
leave
end
if SQLDINFO.1 = dbname then
do
dbdir = SQLDINFO.4
leave
end
end
call SQLDBS 'close database directory :vhandle.1'
dbpath = db_drive'\'dbdir'\'
end
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 RESETLOG. *
* *
* Note: The Report File must already be opened. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
rpthdr:
/* Define Various text lines for the Report */
eqlines = '==================================================' || ,
'============================'
ttline = ' EERESET (V 3.1) Report - ' || date('N') || ' ' || ,
time('C')
dbline = ' Database: ' || dbname
dbpline = ' Database Path: ' || dbpath
seplines = '--------------------------------------------------' || ,
'----------------------------'
/* Construct the Report Header text */
rpthdr_text = ' ' || cr_lf || ,
' ' || cr_lf || ,
eqlines || cr_lf || ,
eqlines || cr_lf || ,
eqlines || cr_lf || ,
eqlines || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
ttline || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
dbline || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
seplines || cr_lf || ,
seplines || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf
/* Write the Report Header to the Report File */
call wrt2rpt rpthdr_text
return
/******************************************************************
* SUBROUTINE: WRT2RPT *
* *
* DESCRIPTIVE NAME: Write to the Report File *
* *
* DESCRIPTION: This routine provides a common routine for *
* writing information to the Report File. This *
* routine checks to verify that the Report File *
* was specified as input to the tool and was *
* subsequently opened before writing the data. *
* *
* INPUT: Text to be written to the Report File *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
wrt2rpt:
parse arg report_text
if report_open = 'YES' then
do
rc = lineout(rptname, report_text)
end
return
/******************************************************************
* SUBROUTINE: FINDLOG *
* *
* DESCRIPTIVE NAME: Find the Path to the Log Files *
* *
* DESCRIPTION: This routine determines the path containing the *
* Log files for the database. *
* *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
findlog:
/*********************************************
Define Offsets to Fields in the Database
Configuration File
*********************************************/
call defoff_dbcon
/*********************************************
Get Data in the Database Configuration File
*********************************************/
call getdata_dbcon
/*********************************************
Determine the Path to the Log Files
*********************************************/
say '....Determining Log File Location'
call getlogpath
return
/******************************************************************
* SUBROUTINE: DEFOFF_DBCON *
* *
* DESCRIPTIVE NAME: Define Offsets to Fields in Database Config *
* *
* DESCRIPTION: This routine defines the offsets for the fields *
* in the Database Configuration File. *
* *
* INPUT: none *
* *
* OUTPUT: none *
* *
******************************************************************/
defoff_dbcon:
/*********************************************
Define Page Offset Constants
(Note: These offsets are 1-origin from the Start of the Page)
(Note: The length values are in terms of character bytes.)
*********************************************/
dbcon = 1 /* Offset to the Database Configuration */
/*********************************************
Define Offsets within the Database Configuration Description
(Note: These offsets are 0-origin from the Start of the
Database Configuration File.)
*********************************************/
dbc_chksumo = 0 /* Checksum field offset */
dbc_chksuml = 4 /* length */
dbc_titleo = 4 /* Title field offset */
dbc_titlel = 12 /* length */
dbc_relo = 16 /* Release field offset */
dbc_rell = 2 /* length */
dbc_pad1o = 18 /* Pad for Long Boundary field offset */
dbc_pad1l = 2 /* length */
dbc_logsizo = 20 /* Log File Size (4K Pages) field offset */
dbc_logsizl = 4 /* length */
dbc_logexto = 24 /* Log File Extent Size field offset */
dbc_logextl = 4 /* length */
dbc_maxexto = 28 /* Max Extents field offset */
dbc_maxextl = 4 /* length */
dbc_dlchko = 32 /* Deadlock Check Interval field offset */
dbc_dlchkl = 4 /* length */
dbc_mseedo = 36 /* Database Seed (masked) field offset */
dbc_mseedl = 4 /* length */
dbc_pad2o = 40 /* Pad field offset */
dbc_pad2l = 4 /* length */
dbc_unseedo = 44 /* Unmasked Database Seed field offset */
dbc_unseedl = 4 /* length */
dbc_stmpo = 48 /* Timestamp field offset */
dbc_stmpl = 10 /* length */
dbc_lcklsto = 58 /* Maximum Storage for LockList offset */
dbc_lcklstl = 2 /* length */
dbc_buffo = 60 /* Size of buffer pool offset */
dbc_buffl = 2 /* length */
dbc_maxfilo = 62 /* Max Db Files Open per appl offset */
dbc_maxfill = 2 /* length */
dbc_softo = 64 /* No. records before Soft Chkpt offset */
dbc_softl = 2 /* length */
dbc_maxappo = 66 /* Max active applications offset */
dbc_maxappl = 2 /* length */
dbc_apheapo = 68 /* Application Heap Size offset */
dbc_apheapl = 2 /* length */
dbc_dbheapo = 70 /* Database Heap Size offset */
dbc_dbheapl = 2 /* length */
dbc_cntryo = 72 /* Country Code of Application offset */
dbc_cntryl = 2 /* length */
dbc_cpago = 74 /* Code Page of Application offset */
dbc_cpagl = 2 /* length */
dbc_agheapo = 76 /* Application Agent Heap Size offset */
dbc_agheapl = 2 /* length */
dbc_maxtoto = 78 /* Max Total Files Open offset */
dbc_maxtotl = 2 /* length */
dbc_slheapo = 80 /* Sort List Heap Size offset */
dbc_slheapl = 2 /* length */
dbc_rdso = 82 /* RDS Version Indicator offset */
dbc_rdsl = 2 /* length */
dbc_pctlckso = 84 /* % of Total LockList per appl offset */
dbc_pctlcksl = 2 /* length */
dbc_stheapo = 86 /* Statement Heap Size offset */
dbc_stheapl = 2 /* length */
dbc_plogo = 88 /* Number of Primary Log Files offset */
dbc_plogl = 2 /* length */
dbc_slogo = 90 /* Number of Secondary Log Files offset */
dbc_slogl = 2 /* length */
dbc_lfsizo = 92 /* Log File Size offset */
dbc_lfsizl = 2 /* length */
dbc_logpatho = 94 /* Log File Path offset */
dbc_logpathl = 248 /* length */
dbc_newpatho = 342 /* Path to the Log File offset */
dbc_newpathl = 248 /* length */
dbc_inflgo = 590 /* Internal Indicator/Status Flag offset */
dbc_inflgl = 2 /* length */
dbc_exflgo = 592 /* External Indicator/Status Flag offset */
dbc_exflgl = 2 /* length */
dbc_pad3o = 594 /* Pad for Spare Bytes offset */
dbc_pad3l = 8 /* length */
return
/******************************************************************
* SUBROUTINE: GETDATA_DBCON *
* *
* DESCRIPTIVE NAME: Get Data from the Db Config File *
* *
* DESCRIPTION: This routine retrieves the data from the *
* Database Configuration File and stores the *
* Database Configuration fields in variables. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
getdata_dbcon:
/*********************************************
Read the Database Configuration File
*********************************************/
/* Checksum */
dbc_chksum = c2d(reverse(charin(dbcon_name, dbcon+dbc_chksumo+2, 2)) || ,
reverse(charin(dbcon_name, dbcon+dbc_chksumo, 2)), 5)
/* Title */
dbc_title = charin(dbcon_name, dbcon+dbc_titleo, dbc_titlel)
/* Release */
dbc_rel = c2x(reverse(charin(dbcon_name, dbcon+dbc_relo, dbc_rell)))
/* Log File Size */
dbc_logsiz = c2d(reverse(charin(dbcon_name, dbcon+dbc_logsizo+2, 2)) || ,
reverse(charin(dbcon_name, dbcon+dbc_logsizo, 2)), 5)
/* Log File Extent Size */
dbc_logext = c2d(reverse(charin(dbcon_name, dbcon+dbc_logexto+2, 2)) || ,
reverse(charin(dbcon_name, dbcon+dbc_logexto, 2)), 5)
/* Max No. of Extents */
dbc_maxext = c2d(reverse(charin(dbcon_name, dbcon+dbc_maxexto+2, 2)) || ,
reverse(charin(dbcon_name, dbcon+dbc_maxexto, 2)), 5)
/* Deadlock Check Interval */
dbc_dlchk = c2d(reverse(charin(dbcon_name, dbcon+dbc_dlchko+2, 2)) || ,
reverse(charin(dbcon_name, dbcon+dbc_dlchko, 2)), 5)
/* Masked Database Seed */
dbc_mseed = c2d(reverse(charin(dbcon_name, dbcon+dbc_mseedo+2, 2)) || ,
reverse(charin(dbcon_name, dbcon+dbc_mseedo, 2)), 5)
/* UnMasked Database Seed */
dbc_unseed = c2d(reverse(charin(dbcon_name, dbcon+dbc_unseedo+2, 2)) || ,
reverse(charin(dbcon_name, dbcon+dbc_unseedo, 2)), 5)
/* Timestamp */
dbc_stmp = c2x(charin(dbcon_name, dbcon+dbc_stmpo, dbc_stmpl))
/* Maximum Storage for Lock List */
dbc_lcklst = c2d(reverse(charin(dbcon_name, dbcon+dbc_lcklsto, dbc_lcklstl)))
/* Size of Buffer Pool */
dbc_buff = c2d(reverse(charin(dbcon_name, dbcon+dbc_buffo, dbc_buffl)))
/* Max Db Files Open per Appl */
dbc_maxfil = c2d(reverse(charin(dbcon_name, dbcon+dbc_maxfilo, dbc_maxfill)))
/* No. Records before Soft Chkpt */
dbc_soft = c2d(reverse(charin(dbcon_name, dbcon+dbc_softo, dbc_softl)))
/* Max Active Applications */
dbc_maxapp = c2d(reverse(charin(dbcon_name, dbcon+dbc_maxappo, dbc_maxappl)))
/* Application Heap Size */
dbc_apheap = c2d(reverse(charin(dbcon_name, dbcon+dbc_apheapo, dbc_apheapl)))
/* Database Heap Size */
dbc_dbheap = c2d(reverse(charin(dbcon_name, dbcon+dbc_dbheapo, dbc_dbheapl)))
/* Country Code */
dbc_cntry = c2d(reverse(charin(dbcon_name, dbcon+dbc_cntryo, dbc_cntryl)))
/* Code Page */
dbc_cpag = c2d(reverse(charin(dbcon_name, dbcon+dbc_cpago, dbc_cpagl)))
/* Application Agent Heap Size */
dbc_agheap = c2d(reverse(charin(dbcon_name, dbcon+dbc_agheapo, dbc_agheapl)))
/* Max Total Files Open */
dbc_maxtot = c2d(reverse(charin(dbcon_name, dbcon+dbc_maxtoto, dbc_maxtotl)))
/* Sort List Heap Size */
dbc_slheap = c2d(reverse(charin(dbcon_name, dbcon+dbc_slheapo, dbc_slheapl)))
/* RDS Version Indicator */
dbc_rds = c2d(reverse(charin(dbcon_name, dbcon+dbc_rdso, dbc_rdsl)))
/* % of Total LockList per Appl */
dbc_pctlcks = c2d(reverse(charin(dbcon_name, dbcon+dbc_pctlckso, dbc_pctlcksl)))
/* Statement Heap Size */
dbc_stheap = c2d(reverse(charin(dbcon_name, dbcon+dbc_stheapo, dbc_stheapl)))
/* Number of Primary Log Files */
dbc_plog = c2d(reverse(charin(dbcon_name, dbcon+dbc_plogo, dbc_plogl)))
/* Number of Secondary Log Files */
dbc_slog = c2d(reverse(charin(dbcon_name, dbcon+dbc_slogo, dbc_slogl)))
/* Log File Size */
dbc_lfsiz = c2d(reverse(charin(dbcon_name, dbcon+dbc_lfsizo, dbc_lfsizl)))
/* Log File Path */
dbc_logpath = charin(dbcon_name, dbcon+dbc_logpatho, dbc_logpathl)
/* New Log File Path */
dbc_newpath = charin(dbcon_name, dbcon+dbc_newpatho, dbc_newpathl)
/* Internal Indicator/Status Flag */
dbc_inflg = c2x(reverse(charin(dbcon_name, dbcon+dbc_inflgo, dbc_inflgl)))
/* External Indicator/Status Flag */
dbc_exflg = c2x(reverse(charin(dbcon_name, dbcon+dbc_exflgo, dbc_exflgl)))
/*********************************************
Report the Contents of the Database
Configuration File
*********************************************/
dbcon_text = ,
' ' || cr_lf || ,
' Database Configuration File ' || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' Checksum: ' || dbc_chksum || cr_lf || ,
' Title: ' || dbc_title || cr_lf || ,
' Release: ' || dbc_rel || cr_lf || ,
' RDS Version Indicator: ' || dbc_rds || cr_lf || ,
' Masked Database Seed: ' || dbc_mseed || cr_lf || ,
' UnMasked Database Seed: ' || dbc_unseed || cr_lf || ,
' Database Creation Timestamp: ' || substr(dbc_stmp,1,4) || '-' || ,
substr(dbc_stmp,5,2) || '-' || ,
substr(dbc_stmp,7,2) || '-' || ,
substr(dbc_stmp,9,2) || '.' || ,
substr(dbc_stmp,11,2) || '.' || ,
substr(dbc_stmp,13,2) || '.' || ,
substr(dbc_stmp,15,6) || ,
cr_lf || ,
' ' || cr_lf || ,
' Log File Size (Linear Log): ' || dbc_logsiz || cr_lf || ,
' Extent Size (Linear Log): ' || dbc_logext || cr_lf || ,
' Max No. of Extents (Linear Log): ' || dbc_maxext || cr_lf || ,
' Number of Primary Log Files: ' || dbc_plog || cr_lf || ,
' Number of Secondary Log Files: ' || dbc_slog || cr_lf || ,
' Size of Each Log File: ' || dbc_lfsiz || cr_lf || ,
' Log File Path: ' || ,
strip(translate(dbc_logpath, ' ', '00'x )) || ,
cr_lf || ,
' New Log File Path: ' || ,
strip(translate(dbc_newpath, ' ', '00'x )) || ,
cr_lf || ,
' ' || cr_lf || ,
' Interval for DeadLock Detection: ' || dbc_dlchk || cr_lf || ,
' Maximum Storage for Lock List: ' || dbc_lcklst || cr_lf || ,
' % of Total Lock List per Appl: ' || dbc_pctlcks || cr_lf || ,
' Maximum Active Applications: ' || dbc_maxapp || cr_lf || ,
' Maximum Db Files Open per Appl: ' || dbc_maxfil || cr_lf || ,
' Max Tot Files Open per Appl: ' || dbc_maxtot || cr_lf || ,
'Records Written before SoftChkpt: ' || dbc_soft || cr_lf || ,
' Size of Buffer Pool: ' || dbc_buff || cr_lf || ,
' ' || cr_lf || ,
' Application Heap Size: ' || dbc_apheap || cr_lf || ,
' Application Agent Heap Size: ' || dbc_agheap || cr_lf || ,
' Database Heap Size: ' || dbc_dbheap || cr_lf || ,
' Statement Heap Size: ' || dbc_stheap || cr_lf || ,
' Sort List Heap Size: ' || dbc_slheap || cr_lf || ,
' ' || cr_lf || ,
' Country Code: ' || dbc_cntry || cr_lf || ,
' Code Page: ' || dbc_cpag || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' -----Internal Indicators----- ' || cr_lf || ,
' ' || cr_lf || ,
' Log File Move Indicator: ' || bitand(dbc_inflg, '0001'x) || ,
cr_lf || ,
' Linear to Circular Log Xlate: ' || bitand(dbc_inflg, '0002'x) || ,
cr_lf || ,
' Circular to Linear Log Xlate: ' || bitand(dbc_inflg, '0004'x) || ,
cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' -----External Indicators----- ' || cr_lf || ,
' ' || cr_lf || ,
' Copy Protect Indicator: ' || bitand(dbc_exflg, '0001'x) || ,
cr_lf
call wrt2rpt dbcon_text
return
/******************************************************************
* SUBROUTINE: GETLOGPATH *
* *
* DESCRIPTIVE NAME: Get the Path Containing Log Files *
* *
* DESCRIPTION: This routine determines the SubDirectory that *
* contains the Log Files from the LOGPATH and *
* NEWPATH fields in the Db Config file. If both *
* fields are NULL, then the Log Files are *
* supposed to be in the Database Subdirectory. *
* The subdirectory supposedly containing the Log *
* Files is checked to see if the Log Control File *
* really exists in the subdirectory. Upon exit *
* from this routine, the shared variable LOGPATH *
* should contain the log file subdirectory. If *
* no subdirectory is found to contain the Log File, *
* then LOGPATH remains a NULL value. *
* *
* INPUT: LOGPATH = NULL *
* *
* *
* OUTPUT: LOGPATH = Log File Subdirectory *
* or *
* LOGPATH = NULL *
* *
******************************************************************/
getlogpath:
/* Construct normalized LogPath character string */
norm_logpath = strip(translate(dbc_logpath, ' ', '00'x ))
/* Construct normalized NewLogPath character string */
norm_newpath = strip(translate(dbc_newpath, ' ', '00'x ))
if norm_logpath = '' & norm_newpath = '' then
do
/* Log Files are supposedly in the database subdirectory */
if stream(dbpath || 'SQL00000.LOG', 'c', 'query exist') \= '' then
logpath = dbpath /* Log File in database subdirectory */
end
else /* Log Path is specified in the Db Configuration */
do
/* Check if Log Control File is specified and found in LOGPATH */
if norm_logpath \= '' & ,
stream(norm_logpath || 'SQL00000.LOG', 'c', 'query exist') \= '' then
/* Log Control File found in LOGPATH */
logpath = norm_logpath
else
do
if norm_newpath \= '' & ,
stream(norm_newpath || 'SQL00000.LOG', 'c', 'query exist') \= '' then
/* Log Control File found in NEWPATH */
logpath = norm_newpath
end
end
return
/******************************************************************
* SUBROUTINE: RESET *
* *
* DESCRIPTIVE NAME: Reset the Log Control File *
* *
* DESCRIPTION: This routine controls the resetting of the Log *
* Control File. It calls a routine to set up the *
* offsets to fields in the Log Control File and *
* then it calls the routine to update the Base *
* LSN in the file. *
* *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
reset:
say '....Examining the Log Control File'
/*********************************************
Define Offsets to Fields in the Log Control File
*********************************************/
call defoff_log
/*********************************************
Write Report File Separator Lines
*********************************************/
rptsep_text = ' ' || cr_lf || ,
' ' || cr_lf || ,
seplines || cr_lf || ,
seplines || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf
call wrt2rpt rptsep_text
/*********************************************
Get Data in the Log Control File
*********************************************/
call getdata_logctl
/*********************************************
Write Report File Separator Lines
*********************************************/
call wrt2rpt rptsep_text
/*********************************************
Get Data in the LOGFILEHEAD Log File
*********************************************/
say '....Examining the LOGFILEHEAD'
call getdata_logfilehead
/*********************************************
Write Report File Separator Lines
*********************************************/
call wrt2rpt rptsep_text
/*********************************************
Get Data in the LOGFILETAIL Log File
*********************************************/
say '....Examining the LOGFILETAIL'
call getdata_logfiletail
/*********************************************
Write Report File Separator Lines
*********************************************/
call wrt2rpt rptsep_text
/*********************************************
Update the Base LSN
*********************************************/
say '....Comparing LSN Values'
call updlsn
/*********************************************
Write the Report File Tail
*********************************************/
rptail_text = ' ' || cr_lf || ,
' ' || cr_lf || ,
eqlines || cr_lf || ,
eqlines || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf
call wrt2rpt rptail_text
return
/******************************************************************
* SUBROUTINE: DEFOFF_LOG *
* *
* DESCRIPTIVE NAME: Define Offsets to Fields in Log Control File *
* *
* DESCRIPTION: This routine defines the offsets for the fields *
* in the Log Control File. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
defoff_log:
/*********************************************
Define Page Offset Constants
(Note: These offsets are 1-origin from the Start of the Page)
(Note: The length values are in terms of character bytes.)
*********************************************/
lfhdr1 = 1 /* Offset to the Primary Log File Header */
lfhdr2 = 2049 /* Offset to the Secondary Log File Header */
lfalt1 = 4097 /* Offset to Partial Page 1 (ALTERNATE1) */
lfalt2 = 8193 /* Offset to Partial Page 2 (ALTERNATE2) */
/*********************************************
Define Offsets for Log File Header in Log Control File
(Note: These offsets are 0-origin from the Start of LFH)
*********************************************/
lfh_cnt1o = 0 /* Consistency Counter 1 field offset */
lfh_cnt1l = 2 /* field length */
lfh_sizeo = 2 /* Number of Bytes in Log File Hdr offset */
lfh_sizel = 2 /* field length */
lfh_logtypo = 4 /* Log File Type field offset */
lfh_logtypl = 2 /* field length */
lfh_logacto = 6 /* Number of Primary Log Files field offset */
lfh_logactl = 2 /* field length */
lfh_loginao = 8 /* Number of Secondary Log Files field offset */
lfh_loginal = 2 /* field length */
lfh_logtoto = 10 /* Total number of files field offset */
lfh_logtotl = 2 /* field length */
lfh_totpago = 12 /* Total Pages field offset */
lfh_totpagl = 4 /* field length */
lfh_totsizo = 16 /* Total Bytes field offset */
lfh_totsizl = 4 /* field length */
lfh_logsizo = 20 /* Number of Pages in each Log field offset */
lfh_logsizl = 2 /* field length */
lfh_ttblsizo = 22 /* Transaction Table Size field offset */
lfh_ttblsizl = 4 /* field length */
lfh_frstpago = 26 /* First Log Page field offset */
lfh_frstpagl = 4 /* field length */
lfh_lastpago = 30 /* Last Log Page field offset */
lfh_lastpagl = 4 /* field length */
lfh_softcnto = 34 /* Soft Checkpoints field offset */
lfh_softcntl = 4 /* field length */
lfh_lfheado = 38 /* File containing Log Head field offset */
lfh_lfheadl = 2 /* field length */
lfh_lfhoffo = 40 /* First Page Number of Log File Head field off */
lfh_lfhoffl = 4 /* field len */
lfh_lftailo = 44 /* File containing Log Tail field offset */
lfh_lftaill = 2 /* field length */
lfh_lftoffo = 46 /* Last Page Number of Log File Tail field off */
lfh_lftoffl = 4 /* field len */
lfh_softmaxo = 50 /* Log Records written before Soft Chkpt off */
lfh_softmaxl = 2 /* field len */
lfh_baselsno = 52 /* First LSN after final Stop Using field off */
lfh_baselsnl = 6 /* field len */
lfh_nextlsno = 58 /* Next LSN prior to final Stop Using field off */
lfh_nextlsnl = 6 /* field len */
lfh_lastlsno = 64 /* LSN of Last Log on Disk field offset */
lfh_lastlsnl = 6 /* field length */
lfh_lowlsno = 70 /* First LSN of Oldest In-Flight Trans field off*/
lfh_lowlsnl = 6 /* field len*/
lfh_minblsno = 76 /* First LSN of Oldest Pg in Buff Pool field off*/
lfh_minblsnl = 6 /* field len*/
lfh_basetido = 82 /* First Transaction ID field offset */
lfh_basetidl = 6 /* field length */
lfh_headlsno = 88 /* LSN at Head of Log File field offset */
lfh_headlsnl = 6 /* field length */
lfh_taillsno = 94 /* Last LSN of Log File field offset */
lfh_taillsnl = 6 /* field length */
lfh_logpatho = 100 /* Log File Path field offset */
lfh_logpathl = 260 /* field length */
lfh_newpatho = 360 /* New Log File Path field offset */
lfh_newpathl = 260 /* field length */
lfh_dbseedo = 620 /* Database Seed field offset */
lfh_dbseedl = 4 /* field length */
lfh_bkpflgo = 624 /* Backup Flag field offset */
lfh_bkpflgl = 2 /* field length */
lfh_resvo = 626 /* Reserved field offset */
lfh_resvl = 2 /* field length */
lfh_handleo = 628 /* File Handle Array field offset */
lfh_handlel = 256 /* field length */
lfh_headcnto = 884 /* Counter incremented before soft checkpoint */
lfh_headcntl = 4 /* */
lfh_pado = 888 /* Pad offset */
lfh_padl = 1158 /* length */
lfh_cnt2o = 2046 /* Consistency counter offset */
lfh_cnt2l = 2 /* length */
/*********************************************
Define Offsets for Log Page Header and Log Page Tail
in Log Pages
(Note: These offsets are 0-origin from the Start
of the Log Page.)
*********************************************/
lph_pglsno = 0 /* Page Header LSN offset */
lph_pglsnl = 6 /* length */
lph_pgnumo = 6 /* Page Number offset */
lph_pgnuml = 4 /* length */
lph_frstidxo = 10 /* Index to First Log Record offset */
lph_frstidxl = 2 /* length */
lph_nxtidxo = 12 /* Index to Next Available Record Space offset */
lph_nxttidxl = 2 /* length */
lph_resvo = 14 /* Reserved Space offset */
lph_resvl = 6 /* length */
lpd_recordo = 20 /* Log Record Data Area offset */
lpd_recordl = 4070 /* length */
lpt_tailsno = 4090 /* Log Page Tail LSN offset */
lpt_tailsnl = 6 /* length */
return
/******************************************************************
* SUBROUTINE: GETDATA_LOGCTL *
* *
* DESCRIPTIVE NAME: Get Data from the Log Control File *
* *
* DESCRIPTION: This routine determines the most recent Log File *
* Header (either the Primary or the Secondary) and *
* retrieves the data from the Log Control File *
* and stores the Log File Header fields in *
* variables. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
getdata_logctl:
/*********************************************
Determine the Current Log File Header
*********************************************/
/* Get the Head Count field from both Log File Headers */
lfh_headcnt1 = c2d(reverse(charin(logctl_name, lfhdr1+lfh_headcnto+2, 2)) || ,
reverse(charin(logctl_name, lfhdr1+lfh_headcnto, 2)), 5)
lfh_headcnt2 = c2d(reverse(charin(logctl_name, lfhdr2+lfh_headcnto+2, 2)) || ,
reverse(charin(logctl_name, lfhdr2+lfh_headcnto, 2)), 5)
/* Compare the Head Count fields from both headers */
if lfh_headcnt1 >= lfh_headcnt2 then /* Primary LFH is most recent */
lfhdr = lfhdr1 /* Set offset for using Primary Log File Header */
else /* Secondary LFH is most recent */
lfhdr = lfhdr2 /* Set offset for using Secondary Log File Header */
/*********************************************
Read the Log Control File
*********************************************/
/* Number of Bytes in Log File Header */
lfh_size = c2d(reverse(charin(logctl_name, lfhdr+lfh_sizeo, lfh_sizel)))
/* Log File Type */
lfh_logtyp = c2d(reverse(charin(logctl_name, lfhdr+lfh_logtypo, lfh_logtypl)))
/* Number of Primary Log Files */
lfh_logact = c2d(reverse(charin(logctl_name, lfhdr+lfh_logacto, lfh_logactl)))
/* Number of Secondary Log Files */
lfh_logina = c2d(reverse(charin(logctl_name, lfhdr+lfh_loginao, lfh_loginal)))
/* Total active/inactive Log Files */
lfh_logtot = c2d(reverse(charin(logctl_name, lfhdr+lfh_logtoto, lfh_logtotl)))
/* Total Pages in Log File */
lfh_totpag = c2d(reverse(charin(logctl_name, lfhdr+lfh_totpago+2, 2)) || ,
reverse(charin(logctl_name, lfhdr+lfh_totpago, 2)), 5)
/* Total Bytes in Log File */
lfh_totsiz = c2d(reverse(charin(logctl_name, lfhdr+lfh_totsizo+2, 2)) || ,
reverse(charin(logctl_name, lfhdr+lfh_totsizo, 2)), 5)
/* Number of pages in each Log File */
lfh_logsiz = c2d(reverse(charin(logctl_name, lfhdr+lfh_logsizo, lfh_logsizl)))
/* Current size of Transaction Table */
lfh_ttblsiz = c2d(reverse(charin(logctl_name, lfhdr+lfh_ttblsizo+2, 2)) || ,
reverse(charin(logctl_name, lfhdr+lfh_ttblsizo, 2)), 5)
/* First Log Page for this header */
lfh_frstpag = c2d(reverse(charin(logctl_name, lfhdr+lfh_frstpago+2, 2)) || ,
reverse(charin(logctl_name, lfhdr+lfh_frstpago, 2)), 5)
/* Last Log Page containing records */
lfh_lastpag = c2d(reverse(charin(logctl_name, lfhdr+lfh_lastpago+2, 2)) || ,
reverse(charin(logctl_name, lfhdr+lfh_lastpago, 2)), 5)
/* Soft Checkpoints since initialization */
lfh_softcnt = c2d(reverse(charin(logctl_name, lfhdr+lfh_softcnto+2, 2)) || ,
reverse(charin(logctl_name, lfhdr+lfh_softcnto, 2)), 5)
/* File containing Beginning of Log */
lfh_lfhead = c2d(reverse(charin(logctl_name, lfhdr+lfh_lfheado, lfh_lfheadl)))
/* LOGFILEHEAD Offset */
lfh_lfhoff = c2d(reverse(charin(logctl_name, lfhdr+lfh_lfhoffo+2, 2)) || ,
reverse(charin(logctl_name, lfhdr+lfh_lfhoffo, 2)), 5)
/* File containing End of Log */
lfh_lftail = c2d(reverse(charin(logctl_name, lfhdr+lfh_lftailo, lfh_lftaill)))
/* LOGFILETAIL Offset */
lfh_lftoff = c2d(reverse(charin(logctl_name, lfhdr+lfh_lftoffo+2, 2)) || ,
reverse(charin(logctl_name, lfhdr+lfh_lftoffo, 2)), 5)
/* # of Log Recs written before soft chkpt */
lfh_softmax = c2d(reverse(charin(logctl_name, lfhdr+lfh_softmaxo, lfh_softmaxl)))
/* First LSN after final Stop Using */
lfh_baselsn = c2x(charin(logctl_name, lfhdr+lfh_baselsno, lfh_baselsnl))
/* Next LSN prior to final Stop Using */
lfh_nextlsn = c2x(charin(logctl_name, lfhdr+lfh_nextlsno, lfh_nextlsnl))
/* LSN of last Log Rec written to disk */
lfh_lastlsn = c2x(charin(logctl_name, lfhdr+lfh_lastlsno, lfh_lastlsnl))
/* First LSN of oldest in-flight trans */
lfh_lowlsn = c2x(charin(logctl_name, lfhdr+lfh_lowlsno, lfh_lowlsnl))
/* First LSN of oldest page in buff pool */
lfh_minblsn = c2x(charin(logctl_name, lfhdr+lfh_minblsno, lfh_minblsnl))
/* First TID after hard checkpoint */
lfh_basetid = c2x(charin(logctl_name, lfhdr+lfh_basetido, lfh_basetidl))
/* LSN of Head of the Log File */
lfh_headlsn = c2x(charin(logctl_name, lfhdr+lfh_headlsno, lfh_headlsnl))
/* Last LSN of the Log File */
lfh_taillsn = c2x(charin(logctl_name, lfhdr+lfh_taillsno, lfh_taillsnl))
/* Log File Path */
lfh_logpath = charin(logctl_name, lfhdr+lfh_logpatho, lfh_logpathl)
/* New Log File Path */
lfh_newpath = charin(logctl_name, lfhdr+lfh_newpatho, lfh_newpathl)
/* Database Seed */
lfh_dbseed = c2d(reverse(charin(logctl_name, lfhdr+lfh_dbseedo+2, 2)) || ,
reverse(charin(logctl_name, lfhdr+lfh_dbseedo, 2)), 5)
/* Backup Flag */
lfh_bkpflg = c2d(reverse(charin(logctl_name, lfhdr+lfh_bkpflgo, lfh_bkpflgl)))
/* Head Counter */
lfh_headcnt = c2d(reverse(charin(logctl_name, lfhdr+lfh_headcnto+2, 2)) || ,
reverse(charin(logctl_name, lfhdr+lfh_headcnto, 2)), 5)
/*********************************************
Report the Contents of the Log File Header
in the Log Control File
*********************************************/
lfh_text = ,
' ' || cr_lf || ,
' Log Control File ' || cr_lf || ,
' Current Log File Header:' || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' Size of Log File Header (bytes): ' || lfh_size || cr_lf || ,
' Log File Type: ' || lfh_logtyp || cr_lf || ,
' ' || cr_lf || ,
' Log File Path: ' || ,
strip(translate(lfh_logpath, ' ', '00'x )) || ,
cr_lf || ,
' New Log File Path: ' || ,
strip(translate(lfh_newpath, ' ', '00'x )) || ,
cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' Number of Primary Log Files: ' || lfh_logact || cr_lf || ,
' Number of Secondary Log Files: ' || lfh_logina || cr_lf || ,
' Total Active/Inactive Files: ' || lfh_logtot || cr_lf || ,
' Total Pages in the Log File: ' || lfh_totpag || cr_lf || ,
'Number of Pages in each Log File: ' || lfh_logsiz || cr_lf || ,
' Total Bytes in the Log File: ' || lfh_totsiz || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' First Log Page: ' || lfh_frstpag || cr_lf || ,
' Last Log Page: ' || lfh_lastpag || cr_lf || ,
' Log File Head: ' || lfh_lfhead || cr_lf || ,
' Log File Head Offset: ' || lfh_lfhoff || cr_lf || ,
' Log File Tail: ' || lfh_lftail || cr_lf || ,
' Log File Tail Offset: ' || lfh_lftoff || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' Base LSN: ' || lfh_baselsn || cr_lf || ,
' Next LSN: ' || lfh_nextlsn || cr_lf || ,
' Last Disk LSN: ' || lfh_lastlsn || cr_lf || ,
' Low Transaction LSN: ' || lfh_lowlsn || cr_lf || ,
' Minimum Buffer LSN: ' || lfh_minblsn || cr_lf || ,
' Head LSN: ' || lfh_headlsn || cr_lf || ,
' Tail LSN: ' || lfh_taillsn || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' First Transaction ID: ' || lfh_basetid || cr_lf || ,
' Size of Transaction Table: ' || lfh_ttblsiz || cr_lf || ,
'Soft Chkpts since Initialization: ' || lfh_softcnt || cr_lf || ,
' Log Recs prior to Soft Chkpt: ' || lfh_softmax || cr_lf || ,
' Database Seed: ' || lfh_dbseed || cr_lf || ,
' Backup Flag: ' || lfh_bkpflg || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf
call wrt2rpt lfh_text
/*********************************************
Read Partial Page 1 in the Log Control File
*********************************************/
/* Page Header LSN */
alt1_pglsn = c2x(charin(logctl_name, lfalt1+lph_pglsno, lph_pglsnl))
/* Page Number */
alt1_pgnum = c2d(reverse(charin(logctl_name, lfalt1+lph_pgnumo+2, 2)) || ,
reverse(charin(logctl_name, lfalt1+lph_pgnumo, 2)), 5)
/* Page Tail LSN */
alt1_tailsn = c2x(charin(logctl_name, lfalt1+lpt_tailsno, lpt_tailsnl))
/*********************************************
Report the Contents of Partial Page 1
in the Log Control File
*********************************************/
alt1_text = ,
' ' || cr_lf || ,
' Log Control File ' || cr_lf || ,
' ' || cr_lf || ,
' Partial Page 1:' || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' Page Number: ' || alt1_pgnum || cr_lf || ,
' Page Header LSN: ' || alt1_pglsn || cr_lf || ,
' Page Tail LSN: ' || alt1_tailsn || cr_lf || ,
' ' || cr_lf
call wrt2rpt alt1_text
/*********************************************
Read Partial Page 2 in the Log Control File
*********************************************/
/* Page Header LSN */
alt2_pglsn = c2x(charin(logctl_name, lfalt2+lph_pglsno, lph_pglsnl))
/* Page Number */
alt2_pgnum = c2d(reverse(charin(logctl_name, lfalt2+lph_pgnumo+2, 2)) || ,
reverse(charin(logctl_name, lfalt2+lph_pgnumo, 2)), 5)
/* Page Tail LSN */
alt2_tailsn = c2x(charin(logctl_name, lfalt2+lpt_tailsno, lpt_tailsnl))
/*********************************************
Report the Contents of Partial Page 2
in the Log Control File
*********************************************/
alt2_text = ,
' ' || cr_lf || ,
' Log Control File ' || cr_lf || ,
' ' || cr_lf || ,
' Partial Page 2:' || cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' Page Number: ' || alt2_pgnum || cr_lf || ,
' Page Header LSN: ' || alt2_pglsn || cr_lf || ,
' Page Tail LSN: ' || alt2_tailsn || cr_lf || ,
' ' || cr_lf
call wrt2rpt alt2_text
return
/******************************************************************
* SUBROUTINE: GETDATA_LOGFILEHEAD *
* *
* DESCRIPTIVE NAME: Get Data from the LOGFILEHEAD Log File *
* *
* DESCRIPTION: This routine determines file name of the *
* LOGFILEHEAD Log File, opens that Log File and *
* retrieves the data from the Log File *
* and stores the Page Header fields in variables. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
getdata_logfilehead:
/*********************************************
Construct the LOGFILEHEAD Log File Name
*********************************************/
lfhead_name = logpath || 'SQL'
if length(lfh_lfhead) < 5 then /* File token less than 5 characters */
/* Concatenate leading 0s to the File Token */
lfhead_name = lfhead_name || copies('0', 5 - length(lfh_lfhead) )
lfhead_name = lfhead_name || lfh_lfhead || '.LOG'
/*********************************************
Initialize the LOGFILEHEAD Log File Page LSN
*********************************************/
lfhead_pglsn = 0
/*********************************************
Check Existence of LOGFILEHEAD Log File
*********************************************/
rc = stream(lfhead_name, 'c', 'query exist')
if rc = '' then
do
say 'The LOGFILEHEAD Log File could not be found.'
error_text = ' ' || cr_lf || ,
'The LOGFILEHEAD Log File could not be found.' || cr_lf || ,
' ' || cr_lf
call wrt2rpt error_text
end
else /* LOGFILEHEAD Log File does exists */
do
/*********************************************
Open the LOGFILEHEAD Log File
*********************************************/
rc = stream(lfhead_name, 'c', 'open')
if (rc = 'READY:') | (rc = 'READY') then
do
/*********************************************
Calculate REXX offset to Start of LOGFILEHEAD
*********************************************/
lfhead_off = lfh_lfhoff + 1
/*********************************************
Read the Page Header from the LOGFILEHEAD
*********************************************/
/* Page Header LSN */
lfhead_pglsn = ,
c2x(charin(lfhead_name, lfhead_off+lph_pglsno, lph_pglsnl))
/* Page Number */
lfhead_pgnum = ,
c2d(reverse(charin(lfhead_name, lfhead_off+lph_pgnumo+2, 2)) || ,
reverse(charin(lfhead_name, lfhead_off+lph_pgnumo, 2)), 5)
/* Page Tail LSN */
lfhead_tailsn = ,
c2x(charin(lfhead_name, lfhead_off+lpt_tailsno, lpt_tailsnl))
/*********************************************
Report the Contents of the Page Header
from LOGFILEHEAD.
*********************************************/
lfhead_text = ,
' ' || cr_lf || ,
' LOGFILEHEAD Log File' || cr_lf || ,
' ' || cr_lf || ,
' ' || lfhead_name || cr_lf || ,
' Log File Page: ' || ,
(lfh_lfhoff % 4096) || ,
cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' Page Number: ' || lfhead_pgnum || ,
cr_lf || ,
' Page Header LSN: ' || lfhead_pglsn || ,
cr_lf || ,
' Page Tail LSN: ' || lfhead_tailsn || ,
cr_lf || ,
' ' || cr_lf
call wrt2rpt lfhead_text
/*********************************************
Close the LOGFILEHEAD Log File
*********************************************/
rc = stream(lfhead_name, 'c', 'close')
end
end
return
/******************************************************************
* SUBROUTINE: GETDATA_LOGFILETAIL *
* *
* DESCRIPTIVE NAME: Get Data from the LOGFILETAIL Log File *
* *
* DESCRIPTION: This routine determines file name of the *
* LOGFILETAIL Log File, opens that Log File and *
* retrieves the data from the Log File *
* and stores the Page Header fields in variables. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
getdata_logfiletail:
/*********************************************
Construct the LOGFILETAIL Log File Name
*********************************************/
lftail_name = logpath || 'SQL'
if length(lfh_lftail) < 5 then /* File token less than 5 characters */
/* Concatenate leading 0s to the File Token */
lftail_name = lftail_name || copies('0', 5 - length(lfh_lftail) )
lftail_name = lftail_name || lfh_lftail || '.LOG'
/*********************************************
Initialize the LOGFILETAIL Log File Page LSN
*********************************************/
lftail_pglsn = 0
/*********************************************
Check Existence of LOGFILETAIL Log File
*********************************************/
rc = stream(lftail_name, 'c', 'query exist')
if rc = '' then
do
say 'The LOGFILETAIL Log File could not be found.'
error_text = ' ' || cr_lf || ,
'The LOGFILETAIL Log File could not be found.' || cr_lf || ,
' ' || cr_lf
call wrt2rpt error_text
end
else /* LOGFILETAIL Log File does exists */
do
/*********************************************
Open the LOGFILETAIL Log File
*********************************************/
rc = stream(lftail_name, 'c', 'open')
if (rc = 'READY:') | (rc = 'READY') then
do
/*********************************************
Calculate offset to Last Page of LOGFILETAIL
*********************************************/
lftail_off = lfh_lftoff + 1
/*********************************************
Read the Page Header from the LOGFILETAIL
*********************************************/
/* Page Header LSN */
lftail_pglsn = ,
c2x(charin(lftail_name, lftail_off+lph_pglsno, lph_pglsnl))
/* Page Number */
lftail_pgnum = ,
c2d(reverse(charin(lftail_name, lftail_off+lph_pgnumo+2, 2)) || ,
reverse(charin(lftail_name, lftail_off+lph_pgnumo, 2)), 5)
/* Page Tail LSN */
lftail_tailsn = ,
c2x(charin(lftail_name, lftail_off+lpt_tailsno, lpt_tailsnl))
/*********************************************
Report the Contents of the Page Header
from LOGFILETAIL.
*********************************************/
lftail_text = ,
' ' || cr_lf || ,
' LOGFILETAIL Log File' || cr_lf || ,
' ' || cr_lf || ,
' ' || lftail_name || cr_lf || ,
' Log File Page: ' || ,
(lfh_lftoff % 4096) || ,
cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf || ,
' Page Number: ' || lftail_pgnum || ,
cr_lf || ,
' Page Header LSN: ' || lftail_pglsn || ,
cr_lf || ,
' Page Tail LSN: ' || lftail_tailsn || ,
cr_lf || ,
' ' || cr_lf
call wrt2rpt lftail_text
/*********************************************
Close the LOGFILETAIL Log File
*********************************************/
rc = stream(lftail_name, 'c', 'close')
end
end
return
/******************************************************************
* SUBROUTINE: UPDLSN *
* *
* DESCRIPTIVE NAME: Update Base LSN *
* *
* DESCRIPTION: This routine updates the Base LSN fields in the *
* Log Control File to effectively reset the Log. *
* It sets the Base LSN to the highest LSN value *
* between the Base LSN itself, and the Page LSNs *
* from the Partial Page 1 of the Log Control File, *
* the Partial Page 2 of the Log Control File, *
* the LOGFILEHEAD, and the LOGFILETAIL. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
updlsn:
baselsn_reset = 'NO' /* Initialize Base LSN reset indicator */
updlsn_text = ,
' ' || cr_lf || ,
' ' || cr_lf || ,
'Base LSN Comparison: ' || cr_lf || ,
' ' || cr_lf || ,
'....Base LSN from Log Control File Header: ' || lfh_baselsn || ,
cr_lf || ,
'....Page LSN from Log Control File Page 1: ' || alt1_pglsn || ,
cr_lf || ,
'....Page LSN from Log Control File Page 2: ' || alt2_pglsn || ,
cr_lf || ,
'................Page LSN from LOGFILEHEAD: ' || lfhead_pglsn || ,
cr_lf || ,
'................Page LSN from LOGFILETAIL: ' || lftail_pglsn || ,
cr_lf || ,
' ' || cr_lf || ,
' ' || cr_lf
call wrt2rpt updlsn_text
/* Reset Base LSN to Partial Page 1 Page LSN if larger */
if lfh_baselsn < alt1_pglsn then
do
lfh_baselsn = alt1_pglsn
baselsn_reset = 'YES'
end
/* Reset Base LSN to Partial Page 2 Page LSN if larger */
if lfh_baselsn < alt2_pglsn then
do
lfh_baselsn = alt2_pglsn
baselsn_reset = 'YES'
end
/* Reset Base LSN to LOGFILEHEAD Page LSN if larger */
if lfh_baselsn < lfhead_pglsn then
do
lfh_baselsn = lfhead_pglsn
baselsn_reset = 'YES'
end
/* Reset Base LSN to LOGFILETAIL Page LSN if larger */
if lfh_baselsn < lftail_pglsn then
do
lfh_baselsn = lftail_pglsn
baselsn_reset = 'YES'
end
if baselsn_reset = 'NO' then
do
/* Increment Base LSN by Log File Size Factor if desired */
/* Note: This routine may cause the Base LSN to be reset */
/* even though it has not been reset yet. */
call quantum_leap
end
if baselsn_reset = 'NO' then
do
say 'The Log appears to be in a reset state and has not been changed.'
error_text = ' ' || cr_lf || ,
'The Log appears to be in a reset state ' || ,
'and has not been changed.' || cr_lf || ,
' ' || cr_lf
call wrt2rpt error_text
end
else
do
/* Write the new Base LSN to the Log Control File */
rc = charout(logctl_name, x2c(lfh_baselsn), lfhdr+lfh_baselsno)
rst_text = ' ' || cr_lf || ,
'The Log has been reset with a new Base LSN of: ' || ,
lfh_baselsn || cr_lf || ,
' ' || cr_lf
say rst_text
call wrt2rpt rst_text
end
return
/******************************************************************
* SUBROUTINE: QUANTUM_LEAP *
* *
* DESCRIPTIVE NAME: Increment the Base LSN by Log File Size *
* *
* DESCRIPTION: This routine prompts the user to determine *
* if they would like to make a Quantum Leap by *
* incrementing the Base LSN by the size of a single *
* Log File. This may be necessary in some cases *
* (in which there has not been a previous soft *
* checkpoint) because the Log Control File will *
* not have the most current LSN information. *
* *
* By incrementing the Base LSN by the size of a *
* single Log File, it is fairly certain that the *
* Base LSN will be incremented to a value which *
* will truly put it in a reset state. *
* *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
quantum_leap:
say " "
say ,
" ╔══════════════════════════════════════════════════════════════════════╗ "
say ,
" ║ ║ "
say ,
" ║ From the information in the Log Control File, the Log already ║ "
say ,
" ║ appears to be in a Reset State. In certain cases, this may ║ "
say ,
" ║ be misleading. ║ "
say ,
" ║ Therefore, would you like to increase the Base LSN in order to ║ "
say ,
" ║ enhance the probability that the Log has actually been ║ "
say ,
" ║ reset? (y/n) ║ "
say ,
" ║ If so, type 'y' and press ENTER; ║ "
say ,
" ║ Otherwise, type 'n' and press ENTER. ║ "
say ,
" ║ ║ "
say ,
" ╚══════════════════════════════════════════════════════════════════════╝ "
say " "
say " "
pull quantum_leap_answer
if quantum_leap_answer = 'Y' then
do
/* Increase the Base LSN by a factor equal to the size of a Log File */
lfh_baselsn = d2x(x2d(lfh_baselsn) + (dbc_logsiz * 4096), (lfh_baselsnl*2))
/* Report the Quantum Leap in the Report File */
leap_text = ' ' || cr_lf || ,
'A Quantum Leap of the Base LSN was requested. ' || ,
' ' || cr_lf || ,
' ' || cr_lf
call wrt2rpt leap_text
/* Set this flag so the new Base LSN will be written to the Log */
baselsn_reset = 'YES'
end
return
/******************************************************************
* SUBROUTINE: GENERAL_HELP *
* *
* DESCRIPTIVE NAME: RESETLOG General Help *
* *
* DESCRIPTION: This routine displays the Help panels for the *
* Reset Log Control File tool. This routine *
* receives control when the input parameter is *
* a "?" instead of the database name. A brief *
* description of the RESETLOG Tool and its *
* syntax is included in the Help panels. *
* *
* INPUT: none *
* *
* *
* OUTPUT: none *
* *
******************************************************************/
general_help:
/* Display help panel */
say " "
say ,
" ┌────────────────────────────────────────────────────────────┐ "
say ,
" │ ┌────────────────────────────────────────┐ │ "
say ,
" │ │ ***** E E R E S E T ***** │ │ "
say ,
" │ │ Reset the Log Control File │ │ "
say ,
" │ │ Version 3.1 │ │ "
say ,
" │ └────────────────────────────────────────┘ │ "
say ,
" │ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ │ "
say ,
" │ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ │ "
say ,
" │ ▀▀▀▀ ▀▀▀ ▀▀▀▀ ▀▀▀▀▀ ▀▀▀▀▀ │ "
say ,
" │ ▀▀▀▀ ▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀ ▀▀▀▀▀▀ │ "
say ,
" │ ▀▀▀▀ ▀▀▀▀▀▀▀▀▀ ▀▀▀ ▀▀▀▀▀ ▀▀▀ │ "
say ,
" │ ▀▀▀▀ ▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀▀ ▀▀▀ │ "
say ,
" │ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀ ▀ ▀▀▀▀ │ "
say ,
" │ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀▀▀ │ "
say ,
" └────────────────────────────────────────────────────────────┘ "
say ,
" ╔══════════════════════════════════════════════════════════════════════╗ "
say ,
" ║ The EERESET Tool is a mechanism for resetting the Log Control ║ "
say ,
" ║ File which governs the recovery of the database from the ║ "
say ,
" ║ Write-Ahead Log. By reseting the Log Control File, the database ║ "
say ,
" ║ will appear to be usable and not need recovery. ║ "
say ,
" ║ CAUTION: The use of this tool will prevent committed changes ║ "
say ,
" ║ which did not make it to media from being recovered and data ║ "
say ,
" ║ integrity could be lost. ║ "
say ,
" ╚══════════════════════════════════════════════════════════════════════╝ "
say " "
'pause'
say " "
say " "
say " "
say " "
say ,
" Syntax: EERESET [dbname] [rptname] "
say " "
say " "
say ,
" where: [dbname] is the alias name of the database. "
say " If no database name is specified , the user "
say " will be prompted for the database name. "
say " "
say " "
say ,
" [rptname] is the report file name. "
say " If no report file name is specified, then no "
say " report will be generated. "
say " "
say " "
say " "
say " "
say " "
say " "
say " "
say " "
return