home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / tarv314.zip / TARRR.CMD < prev    next >
OS/2 REXX Batch file  |  1993-05-14  |  116KB  |  2,792 lines

  1. /*  ************************************************************************  */
  2. /*  MODULE NAME:      TaRRR                                                   */
  3. /*                                                                            */
  4. /*  DESCRIPTIVE NAME: Table Repair/Recover/ReConstruction Tool                */
  5. /*                    Control Program                                         */
  6. /*                                                                            */
  7. /*  LPP NAME:         Standalone Tool                                         */
  8. /*                                                                            */
  9. /*  DESCRIPTION: This routine is responsible for the determination            */
  10. /*               of the local database that is to be inspected and            */
  11. /*               TaRRR'd. It processes the arguments passed as                */
  12. /*               input to the TaRRR Tool and supervises the entire            */
  13. /*               repair in the appropriate sequence.                          */
  14. /*                                                                            */
  15. /*               This module will call the TARNSPEC for the repair            */
  16. /*               and inspection of the table. After the TARNSPEC,             */
  17. /*               it will run through recovery phase and database              */
  18. /*               will be ready for the reconstruction.                        */
  19. /*               It then initiates execution of the Page                      */
  20. /*               ReConstruction Phase of Repair.  This phase                  */
  21. /*               resolves the UnMatched Pointer Records and                   */
  22. /*               generates the Lost Row Report. This program will             */
  23. /*               decide if reorg is required after reconstruction,            */
  24. /*               if reorg is required, it will prompt user for                */
  25. /*               reorg. The final step is the Usable Database                 */
  26. /*               Inspection phase.  If the user has requested                 */
  27. /*               repair of one or more database tables, this                  */
  28. /*               program will prompt the user to determine                    */
  29. /*               whether or not Usable Database Inspection should             */
  30. /*               be executed.  If the user has requested an                   */
  31. /*               inspection only, then this program will bypass               */
  32. /*               the repair, recovery and reconstruction phases               */
  33. /*               and execute the usable database inspection only.             */
  34. /*               Originally, this inspection phase was only                   */
  35. /*               intended for usable databases; however, it has               */
  36. /*               subsequently been changed so a user could                    */
  37. /*               request inspection of a database that cannot be              */
  38. /*               opened.                                                      */
  39. /*                                                                            */
  40. /*                                                                            */
  41. /*  DEPENDENCIES:                                                             */
  42. /*    SYSTEM CONFIRUATION:                                                    */
  43. /*      - OS/2 EE 1.2+                                                        */
  44. /*                                                                            */
  45. /*    LANGUAGE INTERPRETER:                                                   */
  46. /*      - OS/2 Rexx Interpreter                                               */
  47. /*                                                                            */
  48. /*    PREREQUISTIES: None                                                     */
  49. /*                                                                            */
  50. /*                                                                            */
  51. /*  RESTRICTIONS: None                                                        */
  52. /*                                                                            */
  53. /*  INPUT:  Database name                                                     */
  54. /*          Repair Bias                                                       */
  55. /*          Fully-Qualified Single Table Repair Filename                      */
  56. /*          Single Page Repair Number                                         */
  57. /*          Report filename                                                   */
  58. /*                                                                            */
  59. /*                                                                            */
  60. /*  OUTPUT:                                                                   */
  61. /*          Repaired database table(s)                                        */
  62. /*          ReBuilt index(es)                                                 */
  63. /*          Repair Report written to specified file                           */
  64. /*          Return Code stored in REXX host variable 'result'                 */
  65. /*                                                                            */
  66. /*  HOST LANGUAGE: OS/2 Rexx                                                  */
  67. /*                                                                            */
  68. /*  LAST CHANGE DATE: 01/12/92                                                */
  69. /*                                                                            */
  70. /*  Version     Date            Programmer        Reason                      */
  71. /*  ------------------------------------------------------------------------  */
  72. /*  3.04        10/20/92        D.R. Snow         Enhanced messages in        */
  73. /*                                                TaRRR and Resetlog.         */
  74. /*                                                Warn of possible data       */
  75. /*                                                loss.                       */
  76. /*  3.10        10/31/92        D.R. Snow         Whenever repair specified,  */
  77. /*                                                warn of possible data loss. */
  78. /*                                                Let user end program.       */
  79. /*  3.11        12/15/92        D.R. Snow         Add EERESET.CMD             */
  80. /*  3.13        01/06/93        D.R. Snow         Allow Meta flag to be 1 or  */
  81. /*                                                0, and allow new unique     */
  82. /*                                                specifier in index files.   */
  83. /*  3.14        01/06/93        D.R. Snow         Stop processing if it is a  */
  84. /*                                                DB2/2 database.             */
  85. /*                                                                            */
  86. /*  ************************************************************************  */
  87.  
  88. /*********************************************
  89.    turn off trace and echo
  90. *********************************************/
  91.  
  92. '@echo off'
  93.  
  94. TRACE OFF
  95.  
  96. /*********************************************
  97.    Define Flags to Determine Open File Status
  98.    Initialize Constant
  99. *********************************************/
  100.  
  101. rpt_open = 'NO'              /* Open Status for Report File                 */
  102. con_open = 'NO'              /* Open Status for Configuration File          */
  103. boot_open = 'NO'             /* Open Status for BOOT File                   */
  104. dep_open = 'NO'              /* Open Status for .DEP File                   */
  105.  
  106. /*********************************************
  107.    Initialize Phase Status Flags
  108. *********************************************/
  109. start_using = 'NO'         /* Start Using database flag                     */
  110. inspec_step = 'YES'        /* Default status for inspection                 */
  111. recon_step = 'YES'         /* Default status for reconstruction             */
  112. reorg_step = 'YES'         /* Default status for table reorg                */
  113.  
  114.  
  115. numeric digits 15            /* Set Precision for the arithmetic operations */
  116. dbm_already_started = 'YES'  /* Flag to indicate if DbMgr already started
  117.                                    prior to entering this program           */
  118.  
  119. max_tbname_len = 27          /* Max table name length (8.18)                */
  120.  
  121. cr_lf = d2c(13) || d2c(10)    /* Line End characters                        */
  122. global_return = 0             /* Final return code for TaRRR                */
  123.  
  124. cat_flag = 'NO'               /* System Catalog Damaged flag                */
  125. 'rxqueue /clear'              /* clear queue                                */
  126. /*********************************************
  127.    Define all the error messages.
  128. *********************************************/
  129. TAR0006I = "TaRRR Completed: Data rows were lost and known problems exist " || ,
  130.                                "in the database."
  131. TAR0004I = "TaRRR Completed: Known problems exist in the database."
  132. TAR0002I = "TaRRR Completed: Data rows were lost."
  133. TAR0000I = "TaRRR Completed: No known problems remain and no lost rows " || ,
  134.                                "were found."
  135. TAR0002N = "A Disk Full error occurred during repair; the TaRRR Tool " || ,
  136.                                "did not complete."
  137. TAR0004N = "A Write Protect error occurred during repair; the TaRRR Tool " || ,
  138.                                "did not complete."
  139. TAR0006N = "A report file I/O error occurred; the TaRRR Tool did not " || ,
  140.                                "complete."
  141. TAR0008N = "A temporary file I/O error occurred; the TaRRR Tool did not " || ,
  142.                                "complete."
  143. TAR0010N = "A potential file allocation problem has been detected. " || ,
  144.                                "The TaRRR Tool did not complete."
  145. TAR0012N = "An I/O repair failure occurred. The database is in an " || ,
  146.                                "indeterminate state."
  147. TAR0014N = "A system catalog was damaged. The database may not be usable."
  148. TAR0016A = "A system file I/O error occurred in "
  149. TAR0016B = cr_lf || "The TaRRR Tool did not complete. " || ,
  150.            cr_lf || "Verify that all processes are disconnected " || ,
  151.                                "from the database. "
  152. /* ****
  153.    The following message has been replaced with the two previous message
  154.      parts so that the file name may be inserted into the message text.
  155.  
  156.   TAR0016N = "A system file I/O error occurred. The TaRRR Tool did not " || ,
  157.                                "complete. "
  158.    **** */
  159. TAR0018N = "An unexpected memory allocation error occurred; " || ,
  160.                                "the TaRRR Tool did not complete."
  161. TAR0032N = "The database name was not found in the database directories."
  162. TAR0042N = "The table filename is not a valid database table file. "
  163. TAR0044N = "The table filename does not exist.                     "
  164. TAR0052N = "The table page number is not a valid page number.      "
  165. TAR0054N = "The table page number does not exist in the table file."
  166. TAR0062N = "The report file name is not a valid OS/2 filename.     "
  167. TAR0064N = "The path for the report file does not exist.           "
  168. TAR0066N = "The report filename/extension contains words reserved " || ,
  169.            "for temporary repair files."
  170. TAR0072N = "Database Manager registration error"
  171. TAR0082N = "TaRRR cannot be run against a DB2/2 database."
  172.  
  173. /*  ****************  Define some addition return codes  *******************  */
  174. /*  RC = 80 Invalid repair bias specified.                                    */
  175. /*  ***************  End define some addition return codes  ****************  */
  176.  
  177. /*********************************************
  178.    Define all the report header and text
  179. *********************************************/
  180. eqlines = '==================================================' || ,
  181.           '============================'        /* Report Delimiter Lines    */
  182. dashline= '--------------------------------------------------' || ,
  183.           '----------------------------'        /* Report Delimiter Lines    */
  184. title = '          TaRRR (V3.14)  Report   -   ' /* Report Title              */
  185. dbtext= '            Database Name:  '          /* Damaged Database          */
  186. dbsubtext = '    Database Subdirectory:  '      /* Damaged Database Subdir.  */
  187. biatxt = '              Repair Bias:  '         /* Repair Bias               */
  188. biasold = 'Retain Existing Records (OLD)'
  189. biasnew = 'Recover from Write-Ahead Log (NEW)'
  190. biasnsp = 'Database Inspection Only (NSPEC)'
  191. biasnspx= 'Database Inspection with Index ReBuild (NSPECX)'
  192. frctxt = '              ** Force Option Specified **  ' /* Force Option text */
  193. dbcstxt= '                   ** DBCS Database **  '     /* DBCS Database text*/
  194.                                                 /* Db Cfg Indicators         */
  195. cfgtxt = 'One or more of the following Database Configuration Indicators have been reset: '||cr_lf||,
  196.          '                   Copy Protect       '||cr_lf||,
  197.          '                   Enable Log Retain  '||cr_lf||,
  198.          '                   Enable Log Exit    '||cr_lf||,
  199.          '                   Automatic Restart  '||cr_lf
  200. tbtext = '      Data Table Filename:  '         /* Damaged Table File        */
  201. indtext = '               Index Name:  '        /* Index Name                */
  202. tbname = '               Table Name:  '         /* Damaged Table Name        */
  203. pgtext = '      Damaged Page Number:  '         /* Damaged Page Number       */
  204. repbeg = 'Repair Phase Start:      '            /* Inspection Phase Start    */
  205. repend = 'Repair Phase End:        '            /* Inspection Phase End      */
  206. recbeg = 'ReConstruction Phase Start:  '        /* Reconstruction Phase Strt */
  207. recend = 'ReConstruction Phase End:    '        /* Reconstruction Phase End  */
  208. orgbeg = 'ReOrg Phase Start:  '                 /* Reorg Phase Start         */
  209. orgend = 'ReOrg Phase End:  '                   /* Reorg Phase End           */
  210. datbeg = 'Table Inspection Phase Start:  '      /* Tbl Inspection Phase Start*/
  211. datend = 'Table Inspection Phase End:    '      /* Tbl Inspection Phase End  */
  212. chxbeg = 'Index Inspection Phase Start:    '    /* Idx Inspection Phase Start*/
  213. chxend = 'Index Inspection Phase End:      '    /* Idx Inspection Phase End  */
  214. revbeg = 'Recovery Phase Start:  '              /* Recovery Phase Start      */
  215. revend = 'Recovery Phase End:    '              /* Recovery Phase End        */
  216. revsuccess = '... Recovery Successful'          /* Recovery Successful       */
  217. orgsuccess = '... ReOrg Successful   '          /* ReOrg    Successful       */
  218. runsuccess = '... Runstat Successful '          /* RunStat  Successful       */
  219. rbxbeg = 'Index ReBuild Phase Start:  '         /* Index ReBuild Phase Start */
  220. rbxend = 'Index ReBuild Phase End:    '         /* Index ReBuild Phase End   */
  221. prctxt = '....Processing file '                 /* Progress message          */
  222. reptxt  = '  ....No further repair needed'      /* Progress repair message   */
  223. rcntxt  = '  ....No rows lost'                  /* Progress recon message    */
  224. lsttxt  = '  ....*** Rows lost ***'             /* Progress recon message    */
  225. rogtxt = '....Processing table '                /* Progress message          */
  226. cmptxt  = '  ....Complete'                      /* Progress reorg message    */
  227. goodtxt = '  ....No errors found'               /* Progress success message  */
  228. errtxt  = '  ....*** Errors found ***'          /* Progress error message    */
  229.  
  230. reorg_text = cr_lf||cr_lf||,
  231. " ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
  232. " ║    **  NOTICE  **  NOTICE  **  NOTICE  **  NOTICE  **  NOTICE  **    ║ "||cr_lf||,
  233. " ║                                                                      ║ "||cr_lf||,
  234. " ║        THE TABLE NEEDS TO BE REORGANIZED WHENEVER POSSIBLE           ║ "||cr_lf||,
  235. " ║        Would you like to ReOrg the Table now? (y/n)                  ║ "||cr_lf||,
  236. " ║           If so, type 'y' and press ENTER;                           ║ "||cr_lf||,
  237. " ║           Otherwise, type 'n' and press ENTER.                       ║ "||cr_lf||,
  238. " ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
  239. cr_lf ||cr_lf|| cr_lf
  240.  
  241. sqlcheck_text= cr_lf||cr_lf||,
  242. " ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
  243. " ║    **  NOTICE  **  NOTICE  **  NOTICE  **  NOTICE  **  NOTICE  **    ║ "||cr_lf||,
  244. " ║                                                                      ║ "||cr_lf||,
  245. " ║                      USABLE DATABASE INSPECTION                      ║ "||cr_lf||,
  246. " ║                                                                      ║ "||cr_lf||,
  247. " ║           Would you like to run a final inspection of the            ║ "||cr_lf||,
  248. " ║                 specified table(s) and index(es)? (y/n)              ║ "||cr_lf||,
  249. " ║                                                                      ║ "||cr_lf||,
  250. " ║           If so, type 'y' and press ENTER;                           ║ "||cr_lf||,
  251. " ║           Otherwise, type 'n' and press ENTER.                       ║ "||cr_lf||,
  252. " ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
  253. cr_lf ||cr_lf|| cr_lf
  254.  
  255. dbname_text = cr_lf||cr_lf||,
  256. " ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
  257. " ║                                                                      ║ "||cr_lf||,
  258. " ║  Please type the input Database Name and press ENTER:                ║ "||cr_lf||,
  259. " ║                                                                      ║ "||cr_lf||,
  260. " ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
  261. cr_lf ||cr_lf|| cr_lf
  262.  
  263. rptname_text = cr_lf || cr_lf || cr_lf ||,
  264. " ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
  265. " ║                                                                      ║ "||cr_lf||,
  266. " ║  Please type the input Report Filename and press ENTER:              ║ "||cr_lf||,
  267. " ║                                                                      ║ "||cr_lf||,
  268. " ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
  269. cr_lf ||cr_lf|| cr_lf
  270.  
  271. dbcfg_text= cr_lf||cr_lf||,
  272. " ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
  273. " ║    **  NOTICE  **  NOTICE  **  NOTICE  **  NOTICE  **  NOTICE  **    ║ "||cr_lf||,
  274. " ║                                                                      ║ "||cr_lf||,
  275. " ║                   CHANGE TO DATABASE CONFIGURATION                   ║ "||cr_lf||,
  276. " ║                                                                      ║ "||cr_lf||,
  277. " ║  One or more of the following Database Configuration Indicators is   ║ "||cr_lf||,
  278. " ║     being reset to regulate the repair environment:                  ║ "||cr_lf||,
  279. " ║                        Copy Protect                                  ║ "||cr_lf||,
  280. " ║                        Enable Log Retain                             ║ "||cr_lf||,
  281. " ║                        Enable Log Exit                               ║ "||cr_lf||,
  282. " ║                        Automatic Restart                             ║ "||cr_lf||,
  283. " ║                                                                      ║ "||cr_lf||,
  284. " ║  If you want these indicators active, you will have to set them in   ║ "||cr_lf||,
  285. " ║     the Database Configuration after this repair program completes.  ║ "||cr_lf||,
  286. " ║                                                                      ║ "||cr_lf||,
  287. " ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
  288. cr_lf ||cr_lf|| cr_lf
  289.  
  290. warn_dataloss= cr_lf||cr_lf||,
  291. " ╔══════════════════════════════════════════════════════════════════════╗ "||cr_lf||,
  292. " ║ **  WARNING  **  WARNING  **  WARNING  **  WARNING  **  WARNING  **  ║  "||cr_lf||,
  293. " ║                                                                      ║ "||cr_lf||,
  294. " ║               You have asked to repair the database!                 ║ "||cr_lf||,
  295. " ║                ╔════════════════════════════════╗                    ║ "||cr_lf||,
  296. " ║                ║                                ║                    ║ "||cr_lf||,
  297. " ║                ║        DATA MAY BE LOST,       ║                    ║ "||cr_lf||,
  298. " ║                ║    DO YOU WISH TO CONTINUE?    ║                    ║ "||cr_lf||,
  299. " ║                ║                                ║                    ║ "||cr_lf||,
  300. " ║                ╚════════════════════════════════╝                    ║ "||cr_lf||,
  301. " ║                  If so, type 'y' and press ENTER;                    ║ "||cr_lf||,
  302. " ║                Otherwise, type 'n' and press ENTER.                  ║ "||cr_lf||,
  303. " ╚══════════════════════════════════════════════════════════════════════╝ "||cr_lf||,
  304. cr_lf ||cr_lf|| cr_lf
  305.  
  306. /* *********************************************************************** */
  307.  
  308. /*********************************************
  309.    Get the input arguments, ignore the extra
  310.    arguments or non-sense arguments entered by user.
  311. *********************************************/
  312.  
  313. single_tab = 'NO'                  /* default single table option           */
  314. single_page = 'NO'                 /* default single page option            */
  315. bias = 'NEW'                       /* default bias option                   */
  316.  
  317. parse upper arg dbname .
  318. parse upper arg . '/B:' bias .
  319. parse upper arg . '/T:' fname .
  320. parse upper arg . '/P:' inpage .
  321. parse upper arg . '/R:' rptname .
  322. parse upper arg . '/O:' reorg_opt .
  323. parse upper arg . '/I:' nspec_opt .
  324. parse upper arg . '/F:' force_opt .
  325.  
  326. /*********************************************
  327.    Check the Program Input Arguments
  328. *********************************************/
  329. if dbname = '?' then
  330.   do
  331.     global_return = 0                     /*  The TaRRR execution was       */
  332.                                           /*  successful.  Help displayed.  */
  333.     call general_help                     /*  Display the call syntax       */
  334.     signal xit                            /*  Signal to exit.               */
  335.   end
  336.  
  337. /*********************************************
  338.    Register SQLDBS with REXX
  339. *********************************************/
  340. /* Check if SQLDBS function is currently registered                         */
  341. if Rxfuncquery('SQLDBS') \= 0 then
  342.    do
  343.      /* Register SQLDBS function                                            */
  344.      rcy = Rxfuncadd('SQLDBS','SQLAR','SQLDBS')
  345.  
  346.      if rcy \= 0 then
  347.        do
  348.          global_return = -72
  349.          say TAR0072N
  350.          signal xit
  351.        end
  352.    end  /* end if */
  353.  
  354. /*********************************************
  355.    Register SQLEXEC with REXX
  356. *********************************************/
  357. /* Check if SQLEXEC function is currently registered                        */
  358. if Rxfuncquery('SQLEXEC') \= 0 then
  359.    do
  360.      /* Register SQLEXEC function                                           */
  361.      rcy = Rxfuncadd('SQLEXEC','SQLAR','SQLEXEC')
  362.  
  363.      if rcy \= 0 then
  364.        do
  365.          global_return = -72
  366.          say TAR0072N
  367.          signal xit
  368.        end
  369.    end  /* end if */
  370.  
  371. /*********************************************
  372.    Start Database Manager
  373. *********************************************/
  374. call SQLDBS 'START DATABASE MANAGER'
  375. if (sqlca.sqlcode \= 0) & (sqlca.sqlcode \= -1026) then
  376.    call  sqlsit                /* Start Database Manager error encountered  */
  377. else
  378.   do
  379.     if (sqlca.sqlcode = 0) then      /* DbMgr not previously started        */
  380.       dbm_already_started = 'NO'
  381.   end
  382.  
  383. /*********************************************
  384.   Check that we are not running against a back
  385.   level version of the database manager.
  386. *********************************************/
  387. tokens.0 = 2
  388. tokens.1 = 101
  389.  
  390. call SQLDBS 'GET DATABASE MANAGER CONFIGURATION using :tokens'
  391.  
  392. if (sqlca.sqlcode \= 0) then
  393.   do
  394.     global_return = -82     /*  Set return to message no.        */
  395.     say TAR0082N            /*  Tell user cannot run against back*/
  396.                             /*   level of DB.                    */
  397.     signal xit              /*  Exit if wrong version...         */
  398.   end
  399.  
  400. if (tokens.2 > 768) then    /*  DB2/2 is release 0x400           */
  401.   do
  402.     global_return = -82     /*  Set return to message no.        */
  403.     say TAR0082N            /*  Tell user cannot run against back*/
  404.                             /*   level of DB.                    */
  405.     signal xit              /*  Exit if wrong version...         */
  406.   end
  407.  
  408. /*********************************************
  409.    Verify the Input Parameters specified on
  410.        TaRRR Command
  411.    Note: Will also open the Report File, so
  412.            it needs to be after STARTDBM
  413. *********************************************/
  414. call chkargs
  415.  
  416.  
  417. /*********************************************
  418.    Check for Database Inspection Only
  419. *********************************************/
  420. if ((bias = 'NSPEC') | (bias = 'NSPECX')) then
  421.   do
  422.     inspec_step = 'NO'       /* Do not execute the Repair Phase */
  423.     recon_step  = 'NO'       /* Do not execute the ReConstruction Phase */
  424.     reorg_step  = 'NO'       /* Do not prompt for the ReOrg Phase */
  425.   end
  426. else  /*  User requested database repair  Bias = OLD or NEW   */
  427.   do
  428.     'cls'                    /* Clear the screen                              */
  429.     say warn_dataloss        /* Warn of possible data loss                    */
  430.     pull w_resp              /* Get answer, continue or not                   */
  431.  
  432.     if ( (w_resp \= 'Y') & (w_resp \= 'y') ) then
  433.       do
  434.          global_return = 0   /*  The TaRRR execution was successful.          */
  435.          signal xit          /*  Signal to exit.                              */
  436.       end
  437.   end   /*  Continue with Database repair  */
  438.  
  439.  
  440. /*********************************************
  441.    Write the Report Header for TaRRR
  442. *********************************************/
  443. call rpthdr
  444.  
  445.  
  446. /*********************************************
  447.    Read the database signature and the release
  448.      number from Database Configuration File
  449. *********************************************/
  450. call cfgread
  451.  
  452. /*********************************************
  453.    call CATREAD get syscatalog fid
  454. *********************************************/
  455. call catread
  456.  
  457.  
  458. /*********************************************
  459.    If this is Inspection Mode Only, the db
  460.      will be connected later.
  461. *********************************************/
  462. if ((bias \= 'NSPEC') & (bias \= 'NSPECX')) then
  463.   do
  464.     /*********************************************
  465.        Start Using the Database in Exclusive Mode
  466.     *********************************************/
  467.     /* Close Report File in case the Start Using causes a Logon Process
  468.          to be initiated */
  469.     call ficlo 'REPORT'
  470.  
  471.     /* Connect to the Database */
  472.     call sqldbs 'START USING DATABASE ' dbname ' IN EXCLUSIVE MODE'
  473.  
  474.     /* Re-Open the Report File */
  475.     call filop 'REPORT'
  476.  
  477.     /* Error exit if Start Using is Unsuccessful because of some other error
  478.          than Db Needs Recovery when Repair Bias is "OLD" or "NEW"          */
  479.     if ((sqlca.sqlcode \= 0) & (sqlca.sqlcode \= -1015)) then
  480.        call sqlxit
  481.  
  482.     if sqlca.sqlcode = 0 then
  483.        do
  484.           start_using = 'YES'              /* Start Using successful flag   */
  485.     /*                                                                      */
  486.     /* Note: The Stream Command cannot be used on Cruiser because the       */
  487.     /*         wildcard character support was removed.                      */
  488.     /*    if (stream(db_full_path || '*.DRR','c','query exist') = '') then  */
  489.     /*                                                                      */
  490.           'tarfqry ' db_full_path || '*.DRR'
  491.           if (rc \= 0) then
  492.              drr_rc = 'NO'
  493.           else
  494.              drr_rc = 'YES'
  495.     /*                                                                      */
  496.     /* Note: The Stream Command cannot be used on Cruiser because the       */
  497.     /*         wildcard character support was removed.                      */
  498.     /*    if (stream(db_full_path || '*.DEP','c','query exist') = '') then  */
  499.     /*                                                                      */
  500.           'tarfqry ' db_full_path || '*.DEP'
  501.           if (rc \= 0) then
  502.              dep_rc = 'NO'
  503.           else
  504.              dep_rc = 'YES'
  505.  
  506.           if drr_rc = 'YES' then           /* .DRR file exists              */
  507.              do
  508.                 inspec_step = 'NO'         /* no inspection needed          */
  509.                 if dep_rc = 'NO' then      /* if no .DEP exist              */
  510.                    recon_step = 'NO'       /* no reconstruction needed      */
  511.              end
  512.        end
  513.   end
  514.  
  515. /*********************************************
  516.    call TARNSPEC
  517. *********************************************/
  518.  
  519. if inspec_step = 'YES' then            /* If TARNSPEC is required           */
  520.   do
  521.     if single_tab = 'YES' then         /* If single table repair            */
  522.       do
  523.  
  524.          /*********************************************
  525.             Log the Inspection Phase Start Heading
  526.          *********************************************/
  527.          /* Display progress messages */
  528.          say cr_lf || repbeg
  529.          dsp_rc = charout(,prctxt || fname)
  530.  
  531.          /* Log report data */
  532.          call putout repbeg || time('L')
  533.          call putout '     '
  534.          call putout tbtext || fname
  535.          if single_page = 'YES' then
  536.             call putout pgtext || inpage
  537.          call putout  '     '
  538.  
  539.          call inspec                   /* call tarnspec                     */
  540.  
  541.          /*********************************************
  542.             Log the Inspection Phase End Heading
  543.          *********************************************/
  544.          call putout cr_lf || '     '
  545.          call putout repend || time('L')
  546.          call putout '     '
  547.  
  548.       end
  549.     else  /* Multiple Table Repair */
  550.       do
  551.          /* check if any .DAT file exist first                              */
  552.          /*                                                                 */
  553.          /* Note: The Stream Command cannot be used on Cruiser because the  */
  554.          /*         wildcard character support was removed.                 */
  555.          /*                                                                 */
  556.          /* if (stream(db_full_path || 'SQL*.DAT','c','query exist') \= '') then */
  557.          'tarfqry ' db_full_path || 'SQL*.DAT'
  558.          if (rc == 0) then
  559.  
  560.            do
  561.               /*********************************************
  562.                  Log the Inspection Phase Start Heading
  563.               *********************************************/
  564.               say cr_lf || repbeg
  565.               call putout repbeg || time('L')
  566.               call putout '     '
  567.  
  568.               'rxqueue /clear'         /* clear queue                       */
  569.               /* Queue all .DAT Files in the database subdirectory          */
  570.               'dir/f ' db_full_path||'SQL*.DAT | rxqueue /fifo'
  571.               do queued()
  572.                  pull fname            /* Get each .DAT file                */
  573.                  /* Display progress message */
  574.                  dsp_rc = charout(,prctxt || fname)
  575.                  /* Inspect & Repair the file */
  576.                  call inspec
  577.               end
  578.  
  579.               /*********************************************
  580.                  Log the Inspection Phase End Heading
  581.               *********************************************/
  582.               call putout cr_lf || '     '
  583.               call putout repend || time('L')
  584.               call putout '     '
  585.  
  586.            end   /* if any .DAT file exist                                  */
  587.       end   /* not single table option                                      */
  588.  
  589.     call putout dashline
  590.  
  591.     /*********************************************
  592.        Recovery Phase must only be executed if
  593.          the previous Start Using was Unsuccessful
  594.          because the Database Needed Recovery
  595.     *********************************************/
  596.     if start_using = 'NO' then
  597.       do
  598.         /*********************************************
  599.            Log the Recovery Phase Start Heading
  600.         *********************************************/
  601.         say cr_lf || revbeg
  602.         call putout '     '
  603.         call putout revbeg || time('L')
  604.         call putout '     '
  605.  
  606.         /*********************************************
  607.            Recover the Database via the Write-Ahead Log
  608.         *********************************************/
  609.         call sqldbs 'RESTART DATABASE ' dbname
  610.         if sqlca.sqlcode \= 0 then
  611.            call sqlxit
  612.  
  613.         /*********************************************
  614.            Log the Recovery Phase End Heading
  615.         *********************************************/
  616.         call putout revsuccess
  617.         call putout '     '
  618.         call putout revend || time('L')
  619.         call putout '     '
  620.         call putout dashline
  621.  
  622.         /*********************************************
  623.            Start Using the Database in Exclusive Mode
  624.         *********************************************/
  625.         call sqldbs 'START USING DATABASE ' dbname ' IN EXCLUSIVE MODE'
  626.         if sqlca.sqlcode \= 0 then
  627.            call sqlxit
  628.  
  629.         start_using = 'YES'
  630.  
  631.       end  /* Database Needed Recovery   */
  632.  
  633.   end /* if inspec_step = 'YES'                                             */
  634.  
  635. /*********************************************
  636.    Start the ReConstruction Phase
  637. *********************************************/
  638.  
  639. if recon_step = 'YES' then             /* If TARRECON is required           */
  640.    do
  641.       /* check if any .DEP file exist first                                 */
  642.       /*                                                                    */
  643.       /* Note: The Stream Command cannot be used on Cruiser because the     */
  644.       /*         wildcard character support was removed.                    */
  645.       /*                                                                    */
  646.       /* if (stream(db_full_path || '*.DEP','c','query exist') \= '') then  */
  647.       'tarfqry ' db_full_path || '*.DEP'
  648.       if (rc == 0) then
  649.         do
  650.           /*********************************************
  651.              Log the ReConstruction Phase Start Heading
  652.           *********************************************/
  653.           say cr_lf || recbeg
  654.           call putout  '     '
  655.           call putout  recbeg || time('L')
  656.           call putout  '     '
  657.  
  658.           'rxqueue /clear'                               /* clear queue     */
  659.           'dir/f ' db_full_path||'*.DEP | rxqueue /fifo' /* find all .DEP   */
  660.           do queued()
  661.             /* Determine the file name to be reconstructed */
  662.             pull depname                                 /* get each .DEP   */
  663.             tmpfn = FILESPEC('name',depname)
  664.             fname = db_full_path || substr(tmpfn,1,pos('.',tmpfn)) || 'DAT'
  665.  
  666.             /* Display progress message */
  667.             dsp_rc = charout(,prctxt || fname)
  668.  
  669.             /* ReConstruct the table file */
  670.             call recon
  671.           end
  672.  
  673.           /*********************************************
  674.              Log the ReConstruction Phase End Heading
  675.           *********************************************/
  676.           call putout '     '
  677.           call putout recend || time('L')
  678.           call putout '     '
  679.           call putout dashline
  680.  
  681.  
  682.         end  /* if .DEP exist                                               */
  683.    end
  684.  
  685.  
  686. if (start_using = 'YES') then
  687.   do
  688.     /*********************************************
  689.       Issue STOP USING
  690.     *********************************************/
  691.     call sqldbs 'STOP USING DATABASE '
  692.     if sqlca.sqlcode \= 0 then
  693.        call sqlxit
  694.     start_using = 'NO'
  695.   end
  696.  
  697.  
  698. /* If the user has not specified the "Inspection Only" Bias option          */
  699. if reorg_step = 'YES' then
  700.   do
  701.  
  702.     /*********************************************
  703.       Prompt for Reorg of Table if necessary
  704.     *********************************************/
  705.  
  706.     reorg_decision = 'N'                          /* default is NO          */
  707.  
  708.     /* Verify that there are tables needing ReOrg */
  709.     /*                                                                      */
  710.     /* Note: The Stream Command cannot be used on Cruiser because the       */
  711.     /*         wildcard character support was removed.                      */
  712.     /*                                                                      */
  713.     /* if (stream(db_full_path || '*.DRR','c','query exist') \= '') then    */
  714.     'tarfqry ' db_full_path || '*.DRR'
  715.     if (rc == 0) then
  716.       do
  717.         /* Determine user response from Automatic ReOrg Option if specified */
  718.         select
  719.  
  720.           /* Affirmative Automatic ReOrg Option specified */
  721.           when reorg_opt = 'YES' then do
  722.             reorg_decision = 'Y'
  723.           end
  724.  
  725.           /* Negative Automatic ReOrg Option specified */
  726.           when reorg_opt = 'NO' then do
  727.             reorg_decision = 'N'
  728.           end
  729.  
  730.           /* Automatic ReOrg Option not specified, thus user prompted */
  731.           when reorg_opt = '' then do
  732.  
  733.             /* Prompt until a valid response if provided ("Y" or "N")         */
  734.             do forever
  735.               'cls'
  736.               say reorg_text
  737.               pull reorg_decision
  738.               /* Check for a valid response */
  739.               if reorg_decision = 'Y' | reorg_decision = 'N' then
  740.                 leave
  741.             end
  742.           end
  743.         end
  744.  
  745.         if (reorg_decision = 'Y') then
  746.           do
  747.  
  748.             /*********************************************
  749.               Log the ReOrg Phase Start Heading
  750.             *********************************************/
  751.             say cr_lf || orgbeg
  752.             call putout '     '
  753.             call putout orgbeg || time('L')
  754.             call putout '     '
  755.  
  756.             /*********************************************
  757.                Start Using the Database in Exclusive Mode
  758.             *********************************************/
  759.             call sqldbs 'START USING DATABASE ' dbname ' IN EXCLUSIVE MODE'
  760.             if sqlca.sqlcode \= 0 then
  761.                call sqlxit
  762.  
  763.             start_using = 'YES'
  764.  
  765.             /*********************************************
  766.               Check each .DRR file in the database directory
  767.             *********************************************/
  768.             'rxqueue /clear'                      /* clear queue            */
  769.             'dir/f ' db_full_path||'*.DRR | rxqueue /fifo'
  770.             do queued()
  771.  
  772.               pull drrname
  773.               fname = db_full_path || substr(FILESPEC('name',drrname),1,,
  774.                       pos('.',FILESPEC('name',drrname)))||'DAT'
  775.               call querytb                       /* get full table name     */
  776.  
  777.               call putout '     '
  778.               call putout tbname || full_tname
  779.  
  780.               /* Display progress message */
  781.               dsp_rc = charout(,rogtxt || full_tname || ,
  782.                           copies(' ', max_tbname_len - length(full_tname)) )
  783.  
  784.               call SQLDBS 'REORG TABLE ' || full_tname || ' IN ' || dbname
  785.               if sqlca.sqlcode \= 0 then
  786.                 call sqldump
  787.               else
  788.                 call putout orgsuccess
  789.  
  790.               'erase  ' drrname                  /* erase .DRR file         */
  791.               call SQLDBS 'RUNSTATS ON TABLE ' || full_tname || ,
  792.                           ' AND INDEXES ALL '
  793.               if sqlca.sqlcode \= 0 then
  794.                 call sqldump
  795.               else
  796.                 call putout runsuccess
  797.  
  798.               /* Display the completion progress message */
  799.               dsp_rc = charout(,cmptxt || cr_lf)
  800.  
  801.             end                                   /* for each .DRR table    */
  802.  
  803.             /*********************************************
  804.               Issue STOP USING
  805.             *********************************************/
  806.             call sqldbs 'STOP USING DATABASE '
  807.             if sqlca.sqlcode \= 0 then
  808.                call sqlxit
  809.             start_using = 'NO'
  810.  
  811.  
  812.             /*********************************************
  813.               Log the ReOrg Phase End Heading
  814.             *********************************************/
  815.             call putout '     '
  816.             call putout orgend || time('L')
  817.             call putout '     '
  818.             call putout dashline
  819.  
  820.           end  /* If reorg decision is Yes                                  */
  821.         else
  822.           do
  823.             'erase ' db_full_path||'*.DRR'        /* erase all .DRR file    */
  824.           end  /* If reorg decision is NO                                   */
  825.  
  826.       end
  827.  
  828.   end
  829.  
  830. /* The next phase has been previously called the Usable Database Inspection */
  831. /* Originally, this phase was guaranteed to have a usable database on which */
  832. /*   to operate; however, it has been changed to allow inspection of even   */
  833. /*   databases which cannot be opened.  Thus, even though it is still called*/
  834. /*   the Usable Database Inspection in some places to distinguish it from   */
  835. /*   the initial inspection phase of repair, it does now allow the          */
  836. /*   inspection of databases which cannot be connected to via a Start Using.*/
  837.  
  838. /* If "Inspection Only" Bias option specified, then no prompt */
  839. if ((bias = 'NSPEC') | (bias = 'NSPECX')) then
  840.   sqlcheck_decision = 'Y'
  841. else
  842.   /* Repair has been done previously, so prompt for further inspection */
  843.   do
  844.     /* Determine user response from Automatic Inspection Option if specified */
  845.     select
  846.  
  847.       /* Affirmative Automatic Inspection Option specified */
  848.       when nspec_opt = 'YES' then do
  849.         sqlcheck_decision = 'Y'
  850.       end
  851.  
  852.       /* Negative Automatic Inspection Option specified */
  853.       when nspec_opt = 'NO' then do
  854.         sqlcheck_decision = 'N'
  855.       end
  856.  
  857.       /* Automatic Inspection Option not specified, thus user prompted */
  858.       when nspec_opt = '' then do
  859.  
  860.         /*********************************************
  861.           Prompt for Usable Database Inspection
  862.         *********************************************/
  863.  
  864.         /* Prompt until a valid response is provided ("Y" or "N")  */
  865.         do forever
  866.           'cls'
  867.           say sqlcheck_text
  868.           pull sqlcheck_decision
  869.           /* Check for valid response */
  870.           if sqlcheck_decision = 'Y' | sqlcheck_decision = 'N' then
  871.             leave
  872.         end
  873.       end
  874.     end
  875.   end
  876.  
  877. if sqlcheck_decision = 'Y' then
  878.   do
  879.  
  880.      /*********************************************
  881.        Log the Usable Database Inspection
  882.             Phase Start Heading
  883.      *********************************************/
  884.      say cr_lf || datbeg
  885.      call putout  '     '
  886.      call putout  datbeg || time('L')
  887.      call putout  '     '
  888.  
  889.      /*********************************************
  890.         Start Using the Database in Exclusive Mode
  891.         Note: The reason for the Start Using here is retrieving
  892.                 the Table Names from the Systables Catalog in
  893.                 order to relate the Table Name with the OS/2
  894.                 Filename for the user.
  895.               If the Start Using Fails (particularly in Inspection Only
  896.                 Mode), it is sometimes beneficial for the user to
  897.                 continue the inspection even though the Table Names
  898.                 cannot be retrieved.
  899.      *********************************************/
  900.  
  901.      /* Close Report File in case the Start Using causes a Logon Process
  902.           to be initiated                                                    */
  903.      /* Note: This could only happen here when the user has chosen the
  904.                 "Inspection Only" mode                                       */
  905.      call ficlo 'REPORT'
  906.  
  907.      call sqldbs 'START USING DATABASE ' dbname ' IN EXCLUSIVE MODE'
  908.  
  909.      call filop 'REPORT'          /* Re-open the Report File                 */
  910.  
  911.      /* Now that Report File is open, Check the Start Using return code      */
  912.      if sqlca.sqlcode \= 0 then
  913.         call sqldump              /* Record error and continue inspection    */
  914.      else
  915.         start_using = 'YES'       /* Indicate that database is connected     */
  916.  
  917.      /*********************************************
  918.        Inspect the specified Table(s) in the Usable Database
  919.      *********************************************/
  920.      /* Verify that the appropriate table files still exist */
  921.      /*                                                                      */
  922.      /* Note: The Stream Command cannot be used on Cruiser because the       */
  923.      /*         wildcard character support was removed.                      */
  924.      /*                                                                      */
  925.      /*  (stream(db_full_path || 'SQL*.DAT','c','query exist') \= '') )  | , */
  926.      /*                                                                      */
  927.      'tarfqry ' db_full_path || 'SQL*.DAT'
  928.      if ( single_tab = 'NO' & ,
  929.          (rc == 0) ) | ,
  930.         ( single_tab = 'YES' & ,
  931.          (stream(fname,'c','query exist') \= '') ) then
  932.        do
  933.          'rxqueue /clear'                 /* clear queue                    */
  934.          if single_tab = 'YES' then
  935.            /* Push the table filename to be inspected on queue              */
  936.            push fname
  937.          else
  938.            /* Check each .DAT file in the database directory                */
  939.            'dir/f ' db_full_path||'SQL*.DAT | rxqueue /fifo'
  940.          do queued()
  941.             pull fname
  942.             call querytb            /* full_tname will have table name      */
  943.  
  944.             /* Display progress message                                     */
  945.             /* Note: The progress message for a Usable Database contains    */
  946.             /*         the Table Name since it can be retrieved from the    */
  947.             /*         SYSTABLES Catalog;  the progress message for a       */
  948.             /*         Database that cannot be connected to contains the    */
  949.             /*         filename instead of the table name.                  */
  950.             if (start_using = 'YES') then
  951.                dsp_rc = charout(,rogtxt || full_tname || ,
  952.                            copies(' ', max_tbname_len - length(full_tname)) )
  953.             else
  954.                dsp_rc = charout(,prctxt || fname)
  955.  
  956.             call ficlo 'REPORT'     /* close the report file                */
  957.             'tarchdat ' full_tname fname rptname db_signature
  958.             tarchdat_rc = rc
  959.  
  960.             /* Display progress completion message for file */
  961.             if tarchdat_rc = 0 then   /* No errors found */
  962.               dsp_rc = charout(,goodtxt || cr_lf)
  963.             else                      /* Errors found  */
  964.               dsp_rc = charout(,errtxt || cr_lf)
  965.  
  966.             call filop 'REPORT'     /* open the report file                 */
  967.             call handle_error tarchdat_rc
  968.          end
  969.        end
  970.  
  971.      /*********************************************
  972.        Log the Usable Database Inspection Phase End Heading
  973.      *********************************************/
  974.      call putout '     '
  975.      call putout datend || time('L')
  976.      call putout '     '
  977.      call putout dashline
  978.  
  979.      /*********************************************
  980.        Issue STOP USING
  981.      *********************************************/
  982.      if (start_using = 'YES') then
  983.        do
  984.          call sqldbs 'STOP USING DATABASE '
  985.          if sqlca.sqlcode \= 0 then
  986.             call sqldump
  987.          else
  988.             start_using = 'NO'
  989.        end
  990.  
  991.      /*********************************************
  992.        Log the Usable Database Index Inspection Phase Start Heading
  993.      *********************************************/
  994.      say cr_lf || chxbeg
  995.      call putout  '     '
  996.      call putout  chxbeg || time('L')
  997.      call putout  '     '
  998.  
  999.      /*********************************************
  1000.        Inspect the appropriate index(es)
  1001.      *********************************************/
  1002.  
  1003.      /* If the Single Table Option was specified */
  1004.      if single_tab = 'YES' then
  1005.        do
  1006.          /* Create the corresponding index filename */
  1007.          fndrv  = FILESPEC("drive", fname)  /* Drive of the Table File Name  */
  1008.          fnpath = FILESPEC("path", fname)   /* Path of the Table File Name   */
  1009.          tmpfn  = FILESPEC("name", fname)   /* Fname/Ext of Table File Name  */
  1010.          indname = fndrv || fnpath || substr(tmpfn, 1, pos('.', tmpfn)) || 'INX'
  1011.        end
  1012.  
  1013.      /* Verify that the appropriate index files still exist */
  1014.      /*                                                                      */
  1015.      /* Note: The Stream Command cannot be used on Cruiser because the       */
  1016.      /*         wildcard character support was removed.                      */
  1017.      /*                                                                      */
  1018.      /*  (stream(db_full_path || 'SQL*.INX','c','query exist') \= '') )  | , */
  1019.      /*                                                                      */
  1020.      'tarfqry ' db_full_path || 'SQL*.INX'
  1021.      if ( single_tab = 'NO' & ,
  1022.          (rc == 0) ) | ,
  1023.         ( single_tab = 'YES' & ,
  1024.          (stream(indname,'c','query exist') \= '') ) then
  1025.        do
  1026.          'rxqueue /clear'                 /* clear queue                    */
  1027.          if single_tab = 'YES' then
  1028.            /* Push the index filename to be inspected on queue              */
  1029.            push indname
  1030.          else
  1031.            /* Check each .INX file in the database directory                  */
  1032.            'dir/f ' db_full_path||'SQL*.INX | rxqueue /fifo'
  1033.  
  1034.          do queued()
  1035.             pull indname
  1036.  
  1037.             /* Display progress message */
  1038.             dsp_rc = charout(,prctxt || indname)
  1039.  
  1040.  
  1041.             call ficlo 'REPORT'     /* close the report file                */
  1042.             'tarchx ' indname rptname
  1043.             tarchx_rc = rc
  1044.  
  1045.             /* Display progress completion message for file */
  1046.             if tarchx_rc = 0 then   /* No errors found */
  1047.               dsp_rc = charout(,goodtxt || cr_lf)
  1048.             else                      /* Errors found  */
  1049.               dsp_rc = charout(,errtxt || cr_lf)
  1050.  
  1051.             call filop 'REPORT'     /* open the report file                 */
  1052.             call handle_error tarchx_rc
  1053.          end
  1054.        end
  1055.  
  1056.      /*********************************************
  1057.        Log the Usable Database Index Inspection Phase End Heading
  1058.      *********************************************/
  1059.      call putout  '     '
  1060.      call putout  chxend || time('L')
  1061.      call putout  '     '
  1062.      call putout  dashline
  1063.  
  1064.   end  /* If Usable Database Inspection decision is Yes                     */
  1065.  
  1066.  
  1067.  
  1068. /*********************************************
  1069.    Index ReBuild Phase
  1070. *********************************************/
  1071.  
  1072. /* Check to see if any Error Index Files (.EIX) still exist                 */
  1073. /*                                                                          */
  1074. /* Note: The Stream Command cannot be used on Cruiser because the           */
  1075. /*         wildcard character support was removed.                          */
  1076. /*                                                                          */
  1077. /* if stream(db_full_path || 'SQL*.EIX','c','query exist') \= '' then       */
  1078. 'tarfqry ' db_full_path || 'SQL*.EIX'
  1079. if ((rc == 0) & (bias \= 'NSPEC')) then
  1080.   do
  1081.  
  1082.     /*********************************************
  1083.       Log the ReBuild Index Phase Start Heading
  1084.     *********************************************/
  1085.     say cr_lf || rbxbeg
  1086.     call putout  '     '
  1087.     call putout  rbxbeg || time('L')
  1088.     call putout  '     '
  1089.  
  1090.     /*********************************************
  1091.        Start Using the Database in Exclusive Mode
  1092.     *********************************************/
  1093.     call sqldbs 'START USING DATABASE ' dbname ' IN EXCLUSIVE MODE'
  1094.     if sqlca.sqlcode \= 0 then
  1095.        call sqlxit
  1096.  
  1097.     start_using = 'YES'
  1098.  
  1099.  
  1100.     'rxqueue /clear'                 /* clear queue */
  1101.     /* Queue each .EIX file in the database directory */
  1102.     'dir/f ' db_full_path||'SQL*.EIX | rxqueue /fifo'
  1103.  
  1104.     do queued()
  1105.       pull eixname
  1106.  
  1107.       /* Display progress message */
  1108.       dsp_rc = charout(,prctxt || eixname)
  1109.  
  1110.       /* Create the corresponding table filename */
  1111.       eixdrv  = FILESPEC("drive", eixname)  /* Drive of the Error Index File */
  1112.       eixpath = FILESPEC("path", eixname)   /* Path of the Error Index File  */
  1113.       tmpfn  = FILESPEC("name", eixname)   /* Fname/Ext of Error Index File */
  1114.       fname = eixdrv || eixpath || substr(tmpfn, 1, pos('.', tmpfn)) || 'DAT'
  1115.  
  1116.       /* Get the Table Qualifier and Name */
  1117.       call querytb
  1118.  
  1119.       /* Issue a Select Stmt on the Table to ReBuild its Index(es) */
  1120.       stmt3 = "SELECT COUNT(*) FROM  " || full_tname
  1121.  
  1122.       open_cursor = 'NO'                       /* open cursor succeed flag */
  1123.  
  1124.       call SQLEXEC 'PREPARE s3 FROM :stmt3'
  1125.       if sqlca.sqlcode = 0 then
  1126.         do
  1127.           call SQLEXEC 'DECLARE c3 CURSOR FOR s3'
  1128.           if sqlca.sqlcode = 0 then
  1129.             do
  1130.               call SQLEXEC 'Open c3'
  1131.               if sqlca.sqlcode = 0 then
  1132.                 do
  1133.                   call SQLEXEC 'FETCH c3 INTO :tmpcnt'
  1134.                   open_cursor = 'YES'
  1135.                 end
  1136.             end
  1137.         end
  1138.  
  1139.  
  1140.       if open_cursor = 'YES' then
  1141.         do
  1142.           call SQLEXEC 'CLOSE c3'
  1143.         end
  1144.  
  1145.       /* Display the completion progress message */
  1146.       dsp_rc = charout(,cmptxt || cr_lf)
  1147.  
  1148.     end  /* End of loop for ReBuilding Error Index Files */
  1149.  
  1150.     /*********************************************
  1151.       Issue STOP USING
  1152.     *********************************************/
  1153.     call sqldbs 'STOP USING DATABASE '
  1154.     if sqlca.sqlcode \= 0 then
  1155.        call sqlxit
  1156.     start_using = 'NO'
  1157.  
  1158.     /*********************************************
  1159.       Log the ReBuild Index Phase End Heading
  1160.     *********************************************/
  1161.     call putout  '     '
  1162.     call putout  rbxend || time('L')
  1163.     call putout  '     '
  1164.     call putout  dashline
  1165.  
  1166.  
  1167.   end
  1168.  
  1169.  
  1170. /*********************************************
  1171.    Successful Program Completion
  1172. *********************************************/
  1173. result = global_return
  1174.  
  1175. call putout  '     '
  1176.  
  1177. if cat_flag = 'YES' then             /* if syscatalog damaged, put out msg. */
  1178.    call putout TAR0014N
  1179.  
  1180. select
  1181.  
  1182.   when global_return = 0 then do
  1183.     say TAR0000I
  1184.     call putout TAR0000I
  1185.   end
  1186.  
  1187.   when global_return = 2 then do
  1188.     say TAR0002I
  1189.     call putout TAR0002I
  1190.   end
  1191.  
  1192.   when global_return = 4 then do
  1193.     say TAR0004I
  1194.     call putout TAR0004I
  1195.   end
  1196.  
  1197.   when global_return = 6 then do
  1198.     say TAR0006I
  1199.     call putout TAR0006I
  1200.   end
  1201.  
  1202.   when global_return = -12 then do
  1203.     say TAR0012N
  1204.     call putout TAR0012N
  1205.   end
  1206.  
  1207.   otherwise
  1208.  
  1209. end
  1210.  
  1211. signal finish
  1212.  
  1213.  
  1214.  
  1215. /*********************************************
  1216.             PROGRAM  EXITS
  1217. *********************************************/
  1218.  
  1219.  
  1220. /*********************************************
  1221.    Final Program Clean-Up
  1222. *********************************************/
  1223. finish:
  1224.  
  1225.   /* Stop Using the Database */
  1226.   if start_using = 'YES' then
  1227.      call sqldbs 'STOP USING DATABASE'
  1228.  
  1229.   /* Stop DbMgr if started in this program */
  1230.   if dbm_already_started = 'NO' then
  1231.      call SQLDBS 'STOP DATABASE MANAGER'
  1232.  
  1233.   /* Close the SYSBOOT File */
  1234.   if boot_open = 'open' then
  1235.      call ficlo 'BOOT' 'IGNORE'
  1236.  
  1237.   /* Close the Database Configuration File */
  1238.   if con_open = 'open' then
  1239.      call ficlo 'CONFIG' 'IGNORE'
  1240.  
  1241.   /* Close the Input Report File */
  1242.   if rpt_open = 'open' then
  1243.      call ficlo 'REPORT' 'IGNORE'
  1244.  
  1245.   /* Close the DEP File */
  1246.   if dep_open = 'open' then
  1247.      call ficlo 'DEP' 'IGNORE'
  1248.  
  1249.  
  1250. /*  **********************  */
  1251. /*    TaRRR Exit Routine    */
  1252. /*  **********************  */
  1253. xit:
  1254.   result = global_return    /*  Set the return code  */
  1255.   exit result               /*  Exit the program     */
  1256.                             /*  Pass return code     */
  1257.  
  1258. /*  ****************************  */
  1259. /*    TaRRR Error Exit Routine    */
  1260. /*  ****************************  */
  1261. errxit:
  1262.   parse arg msg_text
  1263.   result = global_return
  1264.   say msg_text
  1265.   if (msg_text \= TAR0062N) & (msg_text \= TAR0064N) & (msg_text \= TAR0066N),
  1266.      & (msg_text \= TAR0002N) & (msg_text \= TAR0006N) then
  1267.      do
  1268.         rc = lineout(rptname, '     ')
  1269.         if rc \= 0 then say TAR0006N
  1270.         rc = lineout(rptname, msg_text)
  1271.         if rc \= 0 then say TAR0006N
  1272.      end
  1273.  
  1274.   /* Complete the Tool Cleanup */
  1275.   signal finish
  1276.  
  1277.   return
  1278.  
  1279. /*  ************************************  */
  1280. /*   SQL (Database Manager) Error Exit    */
  1281. /*   Dump error message on screen         */
  1282. /*  ************************************  */
  1283. sqlsit:
  1284.   result = sqlca.sqlcode
  1285.        /* Get the formatted SQL message */
  1286.   call SQLDBS 'GET MESSAGE INTO :sql_msg LINEWIDTH 70'
  1287.   if result = 0 then
  1288.     do
  1289.       /* Formatting successful - Display formatted message */
  1290.       say sql_msg
  1291.     end
  1292.   else
  1293.     do
  1294.       /* Formatting unsuccessful - Display unformatted message */
  1295.       say SQLMSG
  1296.     end
  1297.  
  1298.  
  1299.   /* Complete the Tool Cleanup */
  1300.   signal finish
  1301.  
  1302.  
  1303.   return
  1304.  
  1305. /*********************************************
  1306.    SQL (Database Manager) Error Exit
  1307.    Dump error message on report & on screen
  1308. *********************************************/
  1309. sqlxit:
  1310.  
  1311.   result = sqlca.sqlcode
  1312.  
  1313.   /* Get the formatted SQL message */
  1314.   call SQLDBS 'GET MESSAGE INTO :sql_msg LINEWIDTH 70'
  1315.   if result = 0 then
  1316.     do
  1317.       /* Formatting successful - Display formatted message */
  1318.       say sql_msg
  1319.       call putout sql_msg
  1320.     end
  1321.   else
  1322.     do
  1323.       /* Formatting unsuccessful - Display unformatted message */
  1324.       say SQLMSG
  1325.       call putout SQLMSG
  1326.     end
  1327.  
  1328.   /* Complete the Tool Cleanup */
  1329.   signal finish
  1330.  
  1331.   return
  1332.  
  1333. /*********************************************
  1334.    SQL (Database Manager) Error Dump
  1335. *********************************************/
  1336. sqldump:
  1337.  
  1338.   /* Get the formatted SQL message */
  1339.   call SQLDBS 'GET MESSAGE INTO :sql_msg LINEWIDTH 70'
  1340.   if result = 0 then
  1341.     do
  1342.       /* Formatting successful - Display formatted message */
  1343.       call putout sql_msg
  1344.     end
  1345.   else
  1346.     do
  1347.       /* Formatting unsuccessful - Display unformatted message */
  1348.       call putout SQLMSG
  1349.     end
  1350.  
  1351.   return
  1352.  
  1353.  
  1354. /*********************************************
  1355.               SUBROUTINES
  1356. *********************************************/
  1357.  
  1358. /******************************************************************
  1359. *  SUBROUTINE:   PUTOUT                                           *
  1360. *                                                                 *
  1361. *  DESCRIPTIVE NAME: write the input message into report          *
  1362. *                                                                 *
  1363. *  DESCRIPTION: This routine will write the message into the      *
  1364. *               report, if not successful, the TaRRR will exit    *
  1365. *               with report I/O error.                            *
  1366. *                                                                 *
  1367. *  INPUT: none                                                    *
  1368. *                                                                 *
  1369. *                                                                 *
  1370. *  OUTPUT: none                                                   *
  1371. *                                                                 *
  1372. ******************************************************************/
  1373. putout:
  1374.  
  1375.   parse arg final_msg
  1376.  
  1377.   rc = lineout(rptname,final_msg)
  1378.   if rc \= 0 then
  1379.      do
  1380.        global_return = -6
  1381.        call errxit TAR0006N
  1382.      end
  1383.  
  1384. return
  1385.  
  1386.  
  1387. /******************************************************************
  1388. *  SUBROUTINE:   CHKARGS                                          *
  1389. *                                                                 *
  1390. *  DESCRIPTIVE NAME: Check the Program Input Arguments            *
  1391. *                                                                 *
  1392. *  DESCRIPTION: This routine checks the validity of the input     *
  1393. *               arguments for the program.  If any arguments      *
  1394. *               are not specified, then the user is prompted to   *
  1395. *               type the required argument.                       *
  1396. *                                                                 *
  1397. *  INPUT: none                                                    *
  1398. *                                                                 *
  1399. *                                                                 *
  1400. *  OUTPUT: none                                                   *
  1401. *                                                                 *
  1402. ******************************************************************/
  1403.  
  1404. chkargs:
  1405.  
  1406. /* Verify that the database name (and not an option parameter) was
  1407.      specified first in the command; if not, reprompt for the
  1408.      database name  */
  1409. if substr(dbname, 1, 1) = '/' then
  1410.   dbname = ''
  1411.  
  1412. if dbname = '' then      /* Prompt for the Database name if not input */
  1413.   do
  1414.     'cls'
  1415.     say dbname_text
  1416.     pull dbname
  1417.   end
  1418.  
  1419. if rptname = '' then    /* Prompt for the Report Filename if not input */
  1420.   do
  1421.     say rptname_text
  1422.     pull rptname
  1423.   end
  1424.  
  1425. /*********************************************
  1426.    Validate the Report Filename
  1427. *********************************************/
  1428.  
  1429. /* Terminate if report filename does not have a filename                    */
  1430. if FILESPEC("name", rptname) = ''  then
  1431.    do
  1432.      global_return = -62
  1433.      call errxit  TAR0062N
  1434.    end
  1435.  
  1436. /* Terminate if report filename with SQL or extension with DEP or DRR       */
  1437. if substr(rptname,1,3) = 'SQL' | substr(reverse(rptname),1,4) = 'PED.',
  1438.    | substr(reverse(rptname),1,4) = 'RRD.' then
  1439.    do
  1440.      global_return = -66
  1441.      call errxit  TAR0066N
  1442.    end
  1443.  
  1444. /*********************************************
  1445.    Open the Report File
  1446. *********************************************/
  1447. call filop 'REPORT'
  1448.  
  1449. /*********************************************
  1450.    Determine the full-qualified path of the
  1451.    database subdirectory.
  1452. *********************************************/
  1453.  
  1454. db_drive = ''                      /* drive of the database name            */
  1455. db_subdir = ''                     /* subdirectory of the database name     */
  1456.  
  1457. /* open system database directory                                           */
  1458. inputs = 'OPEN DATABASE DIRECTORY ON 0 USING :db_dir'
  1459. call SQLDBS inputs
  1460. if (sqlca.sqlcode \= 0) then
  1461.    call  sqlxit
  1462.  
  1463.  
  1464. /* find the drive of the database                                           */
  1465. do count = 1 to db_dir.2
  1466.    inputs = 'GET DATABASE DIRECTORY ENTRY :db_dir.1'
  1467.    call SQLDBS inputs
  1468.    if (sqlca.sqlcode \= 0) then
  1469.       call  sqlxit
  1470.    if sqldinfo.1 = dbname then
  1471.      do
  1472.        db_drive = sqldinfo.3
  1473.        leave
  1474.      end
  1475. end  /* end do */
  1476.  
  1477. /* close the database directory                                             */
  1478. inputs = 'CLOSE DATABASE DIRECTORY :db_dir.1'
  1479. call SQLDBS inputs
  1480. if (sqlca.sqlcode \= 0) then
  1481.    call  sqlxit
  1482.  
  1483. /* if the database name is not found in the database system directory       */
  1484. if db_drive = '' then
  1485.    do
  1486.      global_return = -32
  1487.      call errxit  TAR0032N
  1488.    end
  1489.  
  1490. db_drive = strip(db_drive,'t',':')         /* strip out the : of the drive  */
  1491.  
  1492. /* open volume database directory                                           */
  1493. inputs = 'OPEN DATABASE DIRECTORY ON ' || db_drive || ' USING :db_dir'
  1494. call SQLDBS inputs
  1495. if (sqlca.sqlcode \= 0) then
  1496.    call  sqlxit
  1497.  
  1498. /* find the subdirectory of the database                                    */
  1499. do count = 1 to db_dir.2
  1500.    inputs = 'GET DATABASE DIRECTORY ENTRY :db_dir.1'
  1501.    call SQLDBS inputs
  1502.    if (sqlca.sqlcode \= 0) then
  1503.       call  sqlxit
  1504.    if sqldinfo.1 = dbname then
  1505.      do
  1506.        db_subdir = sqldinfo.4
  1507.        leave
  1508.      end
  1509. end  /* end do */
  1510.  
  1511. /* close the database directory                                             */
  1512. inputs = 'CLOSE DATABASE DIRECTORY :db_dir.1'
  1513. call SQLDBS inputs
  1514.  
  1515. /* if the database name is not found in the database directory              */
  1516. if db_subdir = '' then
  1517.    do
  1518.      global_return = -32
  1519.      call errxit  TAR0032N
  1520.    end
  1521. else
  1522.    /* get the path of the database                                          */
  1523.    db_full_path = db_drive || ':\' || db_subdir || '\'
  1524.  
  1525. /*********************************************
  1526.    Get the Repair Bias option set correctly
  1527. *********************************************/
  1528. /* If Repair Bias not specified on          */
  1529. /* command line, use default  NSPEC         */
  1530. if bias = '' then
  1531.   bias = 'NEW'
  1532.  
  1533. /* If invalid Repair Bias specified         */
  1534. /* Display general help error screen        */
  1535. if bias \= 'NEW'  &  bias \= 'OLD'  &  bias \= 'NSPEC'  &  bias \= 'NSPECX' then
  1536.   do
  1537.     global_return = 80  /*  Return a 80,  invalid bias     */
  1538.     call general_help   /*  Display TaRRR syntax.          */
  1539.     signal xit          /*  End the program, invalid bias  */
  1540.   end
  1541.  
  1542. /*********************************************
  1543.    Get the Automatic ReOrg option set correctly
  1544. *********************************************/
  1545. /* Set option to require prompting if specified incorrectly */
  1546. if reorg_opt \= 'YES'  &  reorg_opt \= 'NO' then
  1547.   reorg_opt = ''
  1548.  
  1549. /*********************************************
  1550.    Get the Automatic Usable Database Inspection
  1551.       option set correctly
  1552. *********************************************/
  1553. /* Set option to require prompting if specified incorrectly */
  1554. if nspec_opt \= 'YES'  &  nspec_opt \= 'NO' then
  1555.   nspec_opt = ''
  1556.  
  1557.  
  1558. /*********************************************
  1559.    Get the Single Table and Single Page
  1560.    options set correctly
  1561. *********************************************/
  1562.  
  1563. /* Check for single input table name */
  1564. if fname \= '' then
  1565.    single_tab = 'YES'  /* Single Table Repair/Inspection */
  1566. else  /* Multiple Table Repair/Inspection */
  1567.    fname = 'DUMMY'   /* Set a dummy filename to prevent REXX error */
  1568.  
  1569. /* set the single_page option to YES, if single page option is chosen       */
  1570. if inpage \= '' & single_tab = 'YES' then
  1571.    single_page = 'YES'
  1572.  
  1573. /*********************************************
  1574.    Get the Force Option set correctly
  1575.    Note: The Force Option determines whether
  1576.           or not TaRRR will detect the potential
  1577.           Double Allocation problem.
  1578.          /F:YES means that TaRRR will not detect
  1579.           the Double Allocation problem and repair
  1580.           will continue regardless of its existence.
  1581.          /F:NO means that TaRRR will detect the
  1582.           Double Allocation problem and repair will
  1583.           terminate when it is detected.
  1584.    Note: The Force Option is an undocumented option.
  1585.           Its use should only be exercised by folks
  1586.           willing to take the risk of repairing a
  1587.           table even when there is a potential
  1588.           file system allocation problem.
  1589. *********************************************/
  1590. if force_opt \= 'YES' then
  1591.   force_opt = 'NO'
  1592.  
  1593.  
  1594. /*********************************************
  1595.    Validate the Table Filename, if
  1596.    Single Table option is chosen
  1597. *********************************************/
  1598.  
  1599. /* if single table option was specified, verify the specified filename      */
  1600. if single_tab = 'YES' then
  1601.    do
  1602.       /*Verify that the specified filename is a valid database table file   */
  1603.       if substr(reverse(fname),1,4) \= 'TAD.' | length(fname) \= 24 then
  1604.          do
  1605.            global_return = -42
  1606.            call errxit  TAR0042N
  1607.          end
  1608.  
  1609.       /*Verify that the table file resides in the correct database subdir.  */
  1610.       if (db_full_path\=(FILESPEC("drive",fname)||FILESPEC("path",fname))) then
  1611.          do
  1612.            global_return = -42
  1613.            call errxit TAR0042N
  1614.          end
  1615.  
  1616.       /*Verify that the specified filename does exist                       */
  1617.       if stream(fname, 'C', 'query exist') = '' then
  1618.          do
  1619.            global_return = -44
  1620.            call errxit  TAR0044N
  1621.          end
  1622.  
  1623.    end
  1624.  
  1625. /*********************************************
  1626.    Validate the Page Number, if
  1627.    Single Page option is chosen
  1628. *********************************************/
  1629.  
  1630. /* if single page option was specified, verify the specified page number    */
  1631. if single_page = 'YES' then
  1632.    do
  1633.  
  1634.       /* Verify that the page number is a whole number */
  1635.       if datatype(inpage, 'W') \= 1 then
  1636.         do
  1637.           global_return = -52
  1638.           call errxit TAR0052N
  1639.         end
  1640.  
  1641.       /* Check the page number is a valid page number                       */
  1642.       if inpage < 0 then
  1643.         do
  1644.           global_return = -54
  1645.           call errxit TAR0054N
  1646.         end
  1647.  
  1648.       /* Check the page number does exist in the table file.                */
  1649.       if stream(fname, 'C', 'query size') < ((inpage+1)*4096) then
  1650.         do
  1651.           global_return = -54
  1652.           call errxit  TAR0054N
  1653.         end
  1654.  
  1655.    end
  1656.  
  1657. return
  1658.  
  1659. /******************************************************************
  1660. *  SUBROUTINE:   FILOP                                            *
  1661. *                                                                 *
  1662. *  DESCRIPTIVE NAME: Open the input file                          *
  1663. *                                                                 *
  1664. *  DESCRIPTION: This routine opens the input file. If the file is *
  1665. *               the input Report File, then it also checks the    *
  1666. *               report file for an "End of File" character.       *
  1667. *               If the "End of File" character is found at the    *
  1668. *               end of the file, then the Write Position is       *
  1669. *               set such that any data appended to the file will  *
  1670. *               write over the "End of File" character.           *
  1671. *                                                                 *
  1672. *               The "End of File" character can be inserted by    *
  1673. *               an ASCII Editor when the Report File is viewed    *
  1674. *               and saved.  Then any data appended to the file    *
  1675. *               after the "End of File" code will not be          *
  1676. *               visible in the editor.                            *
  1677. *                                                                 *
  1678. *  INPUT: Type of file being opened (BOOT or CONFIG or REPORT     *
  1679. *         or DEP)                                                 *
  1680. *                                                                 *
  1681. *                                                                 *
  1682. *  OUTPUT: none                                                   *
  1683. *                                                                 *
  1684. ******************************************************************/
  1685.  
  1686. filop:
  1687.  
  1688.   parse upper arg filtyp
  1689.  
  1690.   /* Determine the type of file being opened */
  1691.   select
  1692.  
  1693.     /* The Report File is being opened */
  1694.     when filtyp = 'REPORT' then do
  1695.  
  1696.       if rpt_open = 'NO' then
  1697.         do
  1698.  
  1699.           /* Open the Input Report File */
  1700.           rc = stream(rptname, 'c', 'open')
  1701.  
  1702.           if (rc \= 'READY:') & (rc \= 'READY') then
  1703.             do
  1704.               global_return = -6
  1705.               call errxit  TAR0006N
  1706.             end
  1707.           else
  1708.             do
  1709.               rpt_open = 'YES'
  1710.  
  1711.               /* Locate the last byte in the file */
  1712.               eofpos = stream(rptname, 'c', 'query size')
  1713.  
  1714.               /* Make sure the file is not empty before reading
  1715.                      the last byte */
  1716.               if eofpos > 0 then
  1717.                 do
  1718.  
  1719.                   /* Position the Write Cursor on the last byte
  1720.                        of the file if it is an EOF control;
  1721.                        otherwise leave the Write Cursor positioned
  1722.                        after the last byte */
  1723.                   if charin(rptname, eofpos, 1) = x2c('1A') then
  1724.                     r = stream(rptname, 'c', 'seek -1')
  1725.  
  1726.                 end
  1727.             end
  1728.         end
  1729.       end     /* End of Report File Open */
  1730.  
  1731.     /* The CONFIG File is being opened */
  1732.     when filtyp = 'CONFIG' then do
  1733.  
  1734.       if con_open = 'NO' then
  1735.         do
  1736.  
  1737.           /* Open the Database Configuration File */
  1738.           rc = stream(conname, 'c', 'open')
  1739.  
  1740.           if (rc \= 'READY:') & (rc \= 'READY') then
  1741.             do
  1742.               global_return = -16
  1743.               call errxit TAR0016A || conname || TAR0016B
  1744.             end
  1745.           else
  1746.             con_open = 'YES'
  1747.  
  1748.         end
  1749.       end     /* End of Database Configuration File Open */
  1750.  
  1751.     /* The BOOT File is being opened */
  1752.     when filtyp = 'BOOT' then do
  1753.  
  1754.       if boot_open = 'NO' then
  1755.         do
  1756.  
  1757.           /* Open the Database BOOT File */
  1758.           rc = stream(bootname, 'c', 'open')
  1759.  
  1760.           if (rc \= 'READY:') & (rc \= 'READY') then
  1761.             do
  1762.               global_return = -16
  1763.               call errxit  TAR0016A || bootname || TAR0016B
  1764.             end
  1765.           else
  1766.             boot_open = 'YES'
  1767.  
  1768.         end
  1769.       end     /* End of Database BOOT File Open */
  1770.  
  1771.     /* The DEP File is being opened */
  1772.     when filtyp = 'DEP' then do
  1773.  
  1774.       if dep_open = 'NO' then
  1775.         do
  1776.  
  1777.           /* Open the Input .DEP File */
  1778.           rc = stream(depname, 'c', 'open')
  1779.  
  1780.           if (rc \= 'READY:') & (rc \= 'READY') then
  1781.             do
  1782.               global_return = -8
  1783.               call errxit  TAR0008N
  1784.             end
  1785.           else
  1786.             dep_open = 'YES'
  1787.  
  1788.         end
  1789.       end     /* End of DEP File Open */
  1790.  
  1791.   end    /* End of Select */
  1792.  
  1793.  
  1794. return
  1795.  
  1796.  
  1797.  
  1798. /******************************************************************
  1799. *  SUBROUTINE:   FICLO                                            *
  1800. *                                                                 *
  1801. *  DESCRIPTIVE NAME: Close the file                               *
  1802. *                                                                 *
  1803. *  DESCRIPTION: This routine closes the input file. It also       *
  1804. *               provides an option to ignore errors from the Close*
  1805. *                                                                 *
  1806. *               Ignoring errors will be used during the cleanup   *
  1807. *               at the conclusion of TaRRR.                       *
  1808. *                                                                 *
  1809. *  INPUT: Type of file being opened (BOOT or CONFIG or REPORT     *
  1810. *         or DEP)                                                 *
  1811. *                                                                 *
  1812. *                                                                 *
  1813. *                                                                 *
  1814. *  OUTPUT: none                                                   *
  1815. *                                                                 *
  1816. ******************************************************************/
  1817.  
  1818. ficlo:
  1819.  
  1820.   parse upper arg filtyp erropt
  1821.  
  1822.   rc = 'READY:'    /* Initialize the return code variable */
  1823.  
  1824.   /* Determine the type of file being closed */
  1825.   select
  1826.  
  1827.     /* The Report File is being closed */
  1828.     when filtyp = 'REPORT' then do
  1829.  
  1830.       /* Close the Input Report File */
  1831.       rc = stream(rptname, 'c', 'close')
  1832.  
  1833.       if (erropt \= 'IGNORE') & (rc \= 'READY:') & (rc \= 'READY') then
  1834.         do
  1835.            global_return = -6
  1836.            call errxit TAR0006N
  1837.         end
  1838.       else
  1839.         rpt_open = 'NO'
  1840.  
  1841.       end     /* End of Report File Close */
  1842.  
  1843.     /* The CONFIG File is being closed */
  1844.     when filtyp = 'CONFIG' then do
  1845.  
  1846.       /* Close the Database Configuration File */
  1847.       rc = stream(conname, 'c', 'close')
  1848.  
  1849.       if (erropt \= 'IGNORE') & (rc \= 'READY:') & (rc \= 'READY') then
  1850.         do
  1851.            global_return = -16
  1852.            call errxit TAR0016A || conname || TAR0016B
  1853.         end
  1854.       else
  1855.         con_open = 'NO'
  1856.  
  1857.       end     /* End of Database Configuration File Close */
  1858.  
  1859.     /* The BOOT File is being closed */
  1860.     when filtyp = 'BOOT' then do
  1861.  
  1862.       /* Close the Database BOOT */
  1863.       rc = stream(bootname, 'c', 'close')
  1864.  
  1865.       if (erropt \= 'IGNORE') & (rc \= 'READY:') & (rc \= 'READY') then
  1866.         do
  1867.            global_return = -16
  1868.            call errxit TAR0016A || bootname || TAR0016B
  1869.         end
  1870.       else
  1871.         boot_open = 'NO'
  1872.  
  1873.       end     /* End of Database BOOT File Close */
  1874.  
  1875.     /* The .DEP File is being closed */
  1876.     when filtyp = 'DEP' then do
  1877.  
  1878.       /* Close the .DEP File */
  1879.       rc = stream(depname, 'c', 'close')
  1880.  
  1881.       if (erropt \= 'IGNORE') & (rc \= 'READY:') & (rc \= 'READY') then
  1882.         do
  1883.            global_return = -8
  1884.            call errxit TAR0008N
  1885.         end
  1886.       else
  1887.         dep_open = 'NO'
  1888.  
  1889.       end     /* End of DEP File Close */
  1890.  
  1891.   end    /* End of Select */
  1892.  
  1893.  
  1894.  
  1895. return
  1896.  
  1897.  
  1898. /******************************************************************
  1899. *  SUBROUTINE:   RPTHDR                                           *
  1900. *                                                                 *
  1901. *  DESCRIPTIVE NAME: Write the Report File Header                 *
  1902. *                                                                 *
  1903. *  DESCRIPTION: This routine writes the information that appears  *
  1904. *               at the beginning of the Report for a given        *
  1905. *               execution of TaRRR.                               *
  1906. *                                                                 *
  1907. *               Note: The Report File must already be opened.     *
  1908. *                                                                 *
  1909. *  INPUT: none                                                    *
  1910. *                                                                 *
  1911. *                                                                 *
  1912. *  OUTPUT: none                                                   *
  1913. *                                                                 *
  1914. ******************************************************************/
  1915.  
  1916. rpthdr:
  1917.  
  1918. /* Write space lines */
  1919. call putout '     '
  1920. call putout '     '
  1921.  
  1922. /* Write the Report Delimiter Lines */
  1923. call putout eqlines
  1924. call putout eqlines
  1925. call putout eqlines
  1926. call putout eqlines
  1927.  
  1928. /* Write space lines */
  1929. call putout '     '
  1930. call putout '     '
  1931.  
  1932. /* Write Title line */
  1933. ttline = title || date('N') || '   ' || time('C')
  1934. call putout  ttline
  1935. call putout  '     '
  1936. call putout  '     '
  1937.  
  1938. /* write out the database name */
  1939. dbline = dbtext || dbname
  1940. call putout dbline
  1941.  
  1942. /* write out the database subdirectory */
  1943. dbsubline = dbsubtext || db_full_path
  1944. call putout dbsubline
  1945.  
  1946. call putout '     '
  1947. call putout '     '
  1948.  
  1949. /* Write out the Repair Bias option */
  1950. select
  1951.   when bias = 'OLD' then do
  1952.     bopttxt = biatxt || biasold
  1953.   end
  1954.   when bias = 'NEW' then do
  1955.     bopttxt = biatxt || biasnew
  1956.   end
  1957.   when bias = 'NSPEC' then do
  1958.     bopttxt = biatxt || biasnsp
  1959.   end
  1960.   when bias = 'NSPECX' then do
  1961.     bopttxt = biatxt || biasnspx
  1962.   end
  1963. end
  1964. call putout bopttxt
  1965.  
  1966. /* Write out Force Option text if specified */
  1967. if force_opt = 'YES' then
  1968.   do
  1969.     call putout '     '
  1970.     call putout '     '
  1971.     call putout frctxt
  1972.   end
  1973.  
  1974.  
  1975. call putout '     '
  1976. call putout '     '
  1977.  
  1978. call putout dashline
  1979. call putout dashline
  1980.  
  1981. call putout '     '
  1982.  
  1983.  
  1984. return
  1985.  
  1986. /******************************************************************
  1987. *  SUBROUTINE:   QUERYTB                                          *
  1988. *                                                                 *
  1989. *  DESCRIPTIVE NAME: Query Table Name from file token             *
  1990. *                                                                 *
  1991. *  DESCRIPTION: This routine get the full qualifier table name    *
  1992. *               from SYSTABLES by using FID of table data file    *
  1993. *               and store in the full_tname                       *
  1994. *                                                                 *
  1995. *  INPUT: none                                                    *
  1996. *                                                                 *
  1997. *                                                                 *
  1998. *  OUTPUT: none                                                   *
  1999. *                                                                 *
  2000. ******************************************************************/
  2001.  
  2002. querytb:
  2003.   /*********************************************
  2004.     Determine the Table Name for the Damaged Table File
  2005.   *********************************************/
  2006.  
  2007.    tmpfn  = FILESPEC("name", fname)         /* Filename of Table File       */
  2008.    tab_token = strip(substr(tmpfn, 4, 5),'L',0) /* get file token of table  */
  2009.    stmt2 = "SELECT CREATOR, NAME  FROM SYSIBM.SYSTABLES  ",
  2010.                                  "WHERE FID=" || tab_token
  2011.  
  2012.    tqual = ''                               /* initialize creator           */
  2013.    tname = ''                               /* initialize table name        */
  2014.    open_cursor = 'NO'                       /* open cursor succeed flag     */
  2015.  
  2016.    call SQLEXEC 'PREPARE s2 FROM :stmt2'
  2017.    if sqlca.sqlcode = 0 then
  2018.       do
  2019.          call SQLEXEC 'DECLARE c2 CURSOR FOR s2'
  2020.          if sqlca.sqlcode = 0 then
  2021.          do
  2022.             call SQLEXEC 'Open c2'
  2023.             if sqlca.sqlcode = 0 then
  2024.                do
  2025.                   call SQLEXEC 'FETCH c2 INTO :tqual, :tname'
  2026.                   open_cursor = 'YES'
  2027.                end
  2028.          end
  2029.       end
  2030.  
  2031.    /*********************************************
  2032.      Create the Full Table Name with Qualifier
  2033.    *********************************************/
  2034.    if sqlca.sqlcode \= 0 then
  2035.       do
  2036.          /* Note: Because the "Inspection Only" mode may be inspecting a     */
  2037.          /*         database that cannot be connected to, the error message  */
  2038.          /*         from the above Select is being removed so that it does   */
  2039.          /*         not get repeated over and over.                          */
  2040.          /*       If the table name ends up being "..." on the screen, then  */
  2041.          /*         that is a good indication that a Select error occurred   */
  2042.          /*         and probably a Start Using error occurred prior to that. */
  2043.  
  2044.          /* Handle the special case of SYSBOOT */
  2045.          if tmpfn = 'SQL00001.DAT' then
  2046.            full_tname = 'SYSIBM.SYSBOOT'
  2047.          else       /* the table name is unknown */
  2048.            full_tname = '...'
  2049.       end
  2050.    else
  2051.       full_tname = strip(tqual) || '.' || strip(tname)
  2052.  
  2053.    if open_cursor = 'YES' then
  2054.       do
  2055.          call SQLEXEC 'CLOSE c2'
  2056.       end  /* Close cursor when Open cursor succeed */
  2057.  
  2058.  
  2059. return
  2060.  
  2061. /******************************************************************
  2062. *  SUBROUTINE:   RETAIN_ROW                                       *
  2063. *                                                                 *
  2064. *  DESCRIPTIVE NAME: Dump the retain_row.                         *
  2065. *                                                                 *
  2066. *  DESCRIPTION: This routine will dump the retained rows when     *
  2067. *               repair option biased OLD.                         *
  2068. *                                                                 *
  2069. *  INPUT: none                                                    *
  2070. *                                                                 *
  2071. *                                                                 *
  2072. *  OUTPUT: none                                                   *
  2073. *                                                                 *
  2074. ******************************************************************/
  2075.  
  2076. retain_row:
  2077.  
  2078. call filop 'DEP'                              /* Open DEP file              */
  2079.  
  2080. no_page = c2d(reverse(charin(depname, 1, 4))) /* number of damaged pages    */
  2081.  
  2082. if no_page < 61 then
  2083.    do
  2084.       do i = 1 to no_page
  2085.          damage_page = c2d(reverse(charin(depname, (i*4)+1, 4)))
  2086.          call putout pgtext || damage_page
  2087.          call ficlo 'REPORT'                      /* Close Report File     */
  2088.          'tarddat ' fname  rptname  '-p ' damage_page damage_page
  2089.          call filop 'REPORT'                      /* Open Report File      */
  2090.       end
  2091.    end
  2092.  
  2093. call ficlo 'DEP'                                  /* Close DEP file        */
  2094.  
  2095. return
  2096.  
  2097. /******************************************************************
  2098. *  SUBROUTINE:   VER_CAT                                          *
  2099. *                                                                 *
  2100. *  DESCRIPTIVE NAME: Verify if the table name is one of the       *
  2101. *                      System Catalogs.                           *
  2102. *                                                                 *
  2103. *  DESCRIPTION: This routine will verify the table name to see    *
  2104. *               if it is one of the System Catalogs.  If it is,   *
  2105. *               then cat_flag is set to 'YES'.                    *
  2106. *                                                                 *
  2107. *  INPUT: none                                                    *
  2108. *                                                                 *
  2109. *                                                                 *
  2110. *  OUTPUT: none                                                   *
  2111. *                                                                 *
  2112. ******************************************************************/
  2113.  
  2114. ver_cat:
  2115.  
  2116. if cat_flag = 'NO' then
  2117.    do
  2118.       tmpcat_fname = strip(substr(FILESPEC("name",fname),4),'L','0')
  2119.  
  2120.       do i=1 to 14                              /* for all the syscatalog   */
  2121.          if (catalog.i||'.DAT') = tmpcat_fname then
  2122.             cat_flag = 'YES'
  2123.       end
  2124.  
  2125.       if tmpcat_fname = '1.DAT' then            /* if this is SYSBOOT       */
  2126.          cat_flag = 'YES'
  2127.  
  2128.    end   /* verify only when no syscatalog damaged so far                   */
  2129.  
  2130. return
  2131.  
  2132. /******************************************************************
  2133. *  SUBROUTINE:   CATREAD                                          *
  2134. *                                                                 *
  2135. *  DESCRIPTIVE NAME: Read SYSCATALOG from SYSBOOT file            *
  2136. *                                                                 *
  2137. *  DESCRIPTION: This routine reads the FID of the System          *
  2138. *               Catalogs from the SYSBOOT file and stores those   *
  2139. *               File IDs into a compound variable "catalog" for   *
  2140. *               future comparison.                                *
  2141. *                                                                 *
  2142. *  INPUT: none                                                    *
  2143. *                                                                 *
  2144. *                                                                 *
  2145. *  OUTPUT: none                                                   *
  2146. *                                                                 *
  2147. ******************************************************************/
  2148.  
  2149. catread:
  2150.  
  2151. bootname = db_full_path || 'SQL00001.DAT'
  2152. call filop 'BOOT'
  2153. boot_off = c2d(reverse(charin(bootname, 79, 2)))     /* slot 4              */
  2154. bootstart = 71 + boot_off                            /* boot record offset  */
  2155.  
  2156. /* for more information about sysboot, read sqlrlbot.c                      */
  2157. /* get all 14 FID of syscatalog                                             */
  2158. do i=1 to 14
  2159.    catalog.i = c2d(reverse(charin(bootname, bootstart+16+(i-1)*3, 2)))
  2160. end
  2161.  
  2162. call ficlo 'BOOT'
  2163.  
  2164. return
  2165.  
  2166. /******************************************************************
  2167. *  SUBROUTINE:   CFGREAD                                          *
  2168. *                                                                 *
  2169. *  DESCRIPTIVE NAME: Read Info from the Database Configuration    *
  2170. *                                                                 *
  2171. *  DESCRIPTION: This routine reads the signature and the release  *
  2172. *               from the database configuration file.  The        *
  2173. *               database signature is used to validate each page  *
  2174. *               in the table(s).  The release number is used to   *
  2175. *               determine whether or not the database is a SBCS   *
  2176. *               or DBCS database.                                 *
  2177. *               This routine also checks the external indicators. *
  2178. *               If the Copy Protect, Enable Log Retain, Enable    *
  2179. *               Log Exit, or Automatic Restart are set, then      *
  2180. *               they will be reset.  The most important of these  *
  2181. *               is the resetting of Enable Log Retain to prevent  *
  2182. *               a user from trying to do Roll-Forward Recovery    *
  2183. *               on a repaired database.  The others are more for  *
  2184. *               insurance in the repair environment.              *
  2185. *                                                                 *
  2186. *  INPUT: none                                                    *
  2187. *                                                                 *
  2188. *                                                                 *
  2189. *  OUTPUT: none                                                   *
  2190. *                                                                 *
  2191. ******************************************************************/
  2192.  
  2193. cfgread:
  2194.  
  2195. /* Open the database configuration file                                     */
  2196. conname = db_full_path || 'SQLDBCON'
  2197. call filop 'CONFIG'
  2198.  
  2199. /* Define the offsets and lengths for the necessary fields in the config    */
  2200. dbc_chksumo =  1                    /* Checksum field offset                */
  2201. dbc_chksuml =  4                    /*                length                */
  2202.  
  2203. dbc_rel_off   = 17                  /* Offset of database release field     */
  2204. dbc_rel_len   = 2                   /* Length of database release field     */
  2205.  
  2206. um_seed_off   = 45                  /* Offset of unmasked database seed     */
  2207. um_seed_len   = 4                   /* Length of unmasked database seed     */
  2208.  
  2209. dbc_exflgo =  593                   /* External Indicator/Status Flag offset*/
  2210. dbc_exflgl =  2                     /*                           length     */
  2211.  
  2212. /* Retrieve the database release                                            */
  2213. db_release = c2x(reverse(charin(conname, dbc_rel_off, dbc_rel_len)))
  2214.  
  2215. /* Retrieve the database signature                                          */
  2216. db_signature = c2d(reverse(charin(conname, um_seed_off, um_seed_len)))
  2217.  
  2218.                                     /* External Indicator/Status Flag       */
  2219. dbc_exflg = c2x(reverse(charin(conname, dbc_exflgo, dbc_exflgl)))
  2220.  
  2221. /* Close the database configuration file                                    */
  2222. call ficlo 'CONFIG'
  2223.  
  2224.  
  2225. /* Based on the Database Release, determine whether the database is an SBCS */
  2226. /*    or DBCS database                                                      */
  2227. /* Note: The high nibble of the Release number is '0' for SBCS and          */
  2228. /*         'D' for DBCS                                                     */
  2229. if bitand(x2c(db_release), 'F000'x) = 'D000'x then
  2230.   do
  2231.     char_set = 'D'               /* DBCS Database                           */
  2232.  
  2233.     /* Write out DBCS Database text to Report File */
  2234.     call putout '     '
  2235.     call putout '     '
  2236.     call putout dbcstxt
  2237.  
  2238.     call putout '     '
  2239.     call putout '     '
  2240.  
  2241.     call putout dashline
  2242.     call putout dashline
  2243.  
  2244.     call putout '     '
  2245.   end
  2246.  
  2247. else
  2248.    char_set = 'S'               /* SBCS Database                            */
  2249.  
  2250.  
  2251.  
  2252. /* Check the status of the External Status Flag                             */
  2253. /* If any of the following flags are set,                                   */
  2254. /*   then they are reset prior to continuing the repair.                    */
  2255.  
  2256. /* Get the External Indicator Flag in Character Form                        */
  2257. out_exflg = x2c(dbc_exflg)
  2258.  
  2259. /* Determine state of the following External Indicators:  Copy Protect      */
  2260. /*                                                        Enable Log Retain */
  2261. /*                                                        Enable Log Exit   */
  2262. /*                                                        Automate Restart  */
  2263. /* If one of these indicators is set, then they will be reset in order to   */
  2264. /*   regulate the repair environment by removing potential obstacles to a   */
  2265. /*   successful repair and subsequent use of the repaired database.         */
  2266. /* Note: This only needs to be done during a Repair Mode and not during     */
  2267. /*         the Inspection Only Mode.                                        */
  2268.  
  2269. if ((bias \= 'NSPEC') & (bias \= 'NSPECX') & ,
  2270.     (bitand(out_exflg, '000F'x) \= '0000'x)) then
  2271.   do
  2272.     /* Display the Warning about the Change to the Database Configuration   */
  2273.     'cls'
  2274.     say dbcfg_text
  2275.     'pause'
  2276.  
  2277.     /* Open the Database Configuration File again                           */
  2278.     call filop 'CONFIG'
  2279.  
  2280.     /* Reset the following External Indicators:  Copy Protect               */
  2281.     /*                                           Enable Log Retain          */
  2282.     /*                                           Enable Log Exit            */
  2283.     /*                                           Automatic Restart          */
  2284.     out_exflg = bitand(out_exflg, 'FFF0'x)
  2285.     dbc_exflg = c2x(out_exflg)
  2286.     cfg_rc = charout(conname, reverse(out_exflg), dbc_exflgo)
  2287.  
  2288.  
  2289.     /* Re-calculate the Checksum value */
  2290.  
  2291.     /* Initialize the cursor position to the 5th character */
  2292.     /* Note: The first four characters are the CheckSum value */
  2293.     cursor_pos = 5
  2294.  
  2295.     /* Initialize the checksum value */
  2296.     checksum = 0
  2297.  
  2298.     /* Loop to read each character in the file */
  2299.     do cursor_pos=5 to stream(conname, 'c', 'query size')
  2300.  
  2301.       /* Read the next character */
  2302.       char_value = charin(conname, cursor_pos, 1)
  2303.  
  2304.       /* Add the character to the checksum value */
  2305.       checksum = checksum + c2d(char_value)
  2306.  
  2307.     end
  2308.  
  2309.  
  2310.     /* Set the Write Cursor to the beginning of the Database Configuration file */
  2311.     cfg_rc = stream(conname, 'c', 'seek =1')
  2312.  
  2313.     /* Set the CheckSum field in the Database Configuration to calculated value */
  2314.     dbc_chksum = checksum
  2315.     cfg_rc = charout(conname, reverse(substr(d2c(dbc_chksum, 4), 3, 2)) || ,
  2316.                               reverse(substr(d2c(dbc_chksum, 4), 1, 2)) ,
  2317.                            , dbc_chksumo)
  2318.  
  2319.  
  2320.     /* Close the database configuration file                                    */
  2321.     call ficlo 'CONFIG'
  2322.  
  2323.     /* Write out Config Indicator text to Report File */
  2324.     call putout '     '
  2325.     call putout '     '
  2326.     call putout cfgtxt
  2327.  
  2328.     call putout '     '
  2329.     call putout '     '
  2330.  
  2331.     call putout dashline
  2332.     call putout dashline
  2333.  
  2334.     call putout '     '
  2335.  
  2336.   end
  2337.  
  2338.  
  2339. return
  2340.  
  2341. /******************************************************************
  2342. *  SUBROUTINE:   INSPEC                                           *
  2343. *                                                                 *
  2344. *  DESCRIPTIVE NAME: Initiate the Inspection/Repair Phase         *
  2345. *                                                                 *
  2346. *  DESCRIPTION: This routine calls TARNSPEC to initiate the       *
  2347. *               Inspection/Repair Phase of TaRRR.                 *
  2348. *                                                                 *
  2349. *  INPUT: none                                                    *
  2350. *                                                                 *
  2351. *                                                                 *
  2352. *  OUTPUT: none                                                   *
  2353. *                                                                 *
  2354. ******************************************************************/
  2355.  
  2356. inspec:
  2357.  
  2358.   /*********************************************
  2359.      Get the option flag
  2360.   *********************************************/
  2361.  
  2362.   fndrv  = FILESPEC("drive", fname)     /* Drive of the Table File Name     */
  2363.   fnpath = FILESPEC("path", fname)      /* Path of the Table File Name      */
  2364.   tmpfn  = FILESPEC("name", fname)      /* Filename/Ext of Table File Name  */
  2365.   indname = fndrv || fnpath || substr(tmpfn, 1, pos('.', tmpfn)) || 'INX'
  2366.  
  2367.   option_flag = 0                       /* default to no index, biased NEW  */
  2368.  
  2369.   /* if index exist, then set 1st-bit to 1                                  */
  2370.   if stream(indname, 'C', 'query exist') \= '' then
  2371.      option_flag = c2d(bitor(d2c(option_flag), '01'x))
  2372.  
  2373.   /* if option biased OLD, then set 2nd-bit to 1                            */
  2374.   if bias = 'OLD' then
  2375.      option_flag = c2d(bitor(d2c(option_flag), '02'x))
  2376.  
  2377.   /* Set up the Force Opt for the Inspection Program */
  2378.   if force_opt = 'YES' then
  2379.      option_flag = c2d(bitor(d2c(option_flag), '04'x))
  2380.  
  2381.   /* Set up the DBCS Opt for the Inspection Program */
  2382.   if char_set = 'D' then
  2383.      option_flag = c2d(bitor(d2c(option_flag), '08'x))
  2384.  
  2385.  
  2386.   call ficlo 'REPORT'               /* close the report file                */
  2387.  
  2388.   if single_page = 'NO' then        /* call the inspection program          */
  2389.      'tarnspec ' fname rptname db_signature option_flag
  2390.   else
  2391.      'tarnspec ' fname rptname db_signature option_flag '/P:'inpage
  2392.  
  2393.   inspec_rc = rc                    /* save return code of the inspection   */
  2394.  
  2395.   /* Display progress completion message for file */
  2396.   select
  2397.     when inspec_rc = 0 then  /* No errors found */
  2398.       dsp_rc = charout(,goodtxt || cr_lf)
  2399.     when inspec_rc = 2 then  /* No further repair necessary */
  2400.       dsp_rc = charout(,reptxt || cr_lf)
  2401.     otherwise                /* Errors or ReConstruction required */
  2402.       dsp_rc = charout(,errtxt || cr_lf)
  2403.   end
  2404.  
  2405.   call filop 'REPORT'               /* Open the Report File                 */
  2406.  
  2407.   /* Handle return codes from TARNSPEC                                      */
  2408.   /* Note: The non-fatal return codes "Errors found and Page does not       */
  2409.   /*         Require ReConstruction (2)" and "Page Requires ReConstruction  */
  2410.   /*         (4)" should not be preserved in global_return so handle_error  */
  2411.   /*         will not be called in that case.  These return codes are       */
  2412.   /*         essentially ignored at this point.  The existence of .DEP files*/
  2413.   /*         will be used to determine the necessity for ReConstruction.    */
  2414.   if inspec_rc > 10 then
  2415.     call handle_error inspec_rc     /* handle error return                  */
  2416.  
  2417.   if inspec_rc \= 0 then            /* verify if a syscatalog or not        */
  2418.      call ver_cat
  2419.  
  2420. return
  2421.  
  2422.  
  2423. /******************************************************************
  2424. *  SUBROUTINE:   RECON                                            *
  2425. *                                                                 *
  2426. *  DESCRIPTIVE NAME: Initiate the ReConstruction Phase            *
  2427. *                                                                 *
  2428. *  DESCRIPTION: This routine calls TARRECON to initiate the       *
  2429. *               ReConstruction Phase of Table Repair.  It will    *
  2430. *               resolve any UnMatched Pointer Records in the      *
  2431. *               table as well as generate the Lost Row Report     *
  2432. *               thru the use of keys in a unique index.           *
  2433. *                                                                 *
  2434. *  INPUT: none                                                    *
  2435. *                                                                 *
  2436. *                                                                 *
  2437. *  OUTPUT: none                                                   *
  2438. *                                                                 *
  2439. ******************************************************************/
  2440.  
  2441. recon:
  2442.  
  2443.   /*********************************************
  2444.      Determine the Internal Index ID of the
  2445.         smallest colcount of the unique index
  2446.   *********************************************/
  2447.  
  2448.   tmpfn  = FILESPEC("name", fname)              /* Filename of Table File */
  2449.   tab_token = strip(substr(tmpfn, 4, 5),'L',0)  /* get file token of table */
  2450.  
  2451.   stmt1 = "SELECT IID, COLCOUNT, NAME, CREATOR, COLNAMES FROM ",
  2452.           "SYSIBM.SYSINDEXES WHERE TBNAME=",
  2453.           "ANY (SELECT NAME FROM SYSIBM.SYSTABLES WHERE FID="||tab_token|| ")",
  2454.           "AND TBCREATOR = ANY (SELECT CREATOR FROM SYSIBM.SYSTABLES WHERE FID=",
  2455.           ||tab_token|| ")  AND (UNIQUERULE = 'P' OR UNIQUERULE = 'U')",
  2456.           " ORDER BY COLCOUNT"
  2457.  
  2458.                             /* Initialize the index related variables       */
  2459.   iid = 0                   /*     Internal Index ID                        */
  2460.  
  2461.   call SQLEXEC 'PREPARE s1 FROM :stmt1'
  2462.   if (sqlca.sqlcode = 0) then
  2463.     do
  2464.       call SQLEXEC 'DECLARE c1 CURSOR FOR s1'
  2465.       if (sqlca.sqlcode = 0) then
  2466.         do
  2467.           call SQLEXEC 'Open c1'
  2468.           if (sqlca.sqlcode = 0) then
  2469.             do
  2470.               call SQLEXEC 'FETCH c1 INTO :iid, :colcount, :name, :creator, :colnames'
  2471.               call SQLEXEC 'CLOSE c1'
  2472.             end   /* open cursor successful                                 */
  2473.         end   /* declare successful                                         */
  2474.     end   /* Prepare successful                                             */
  2475.  
  2476.   /* Initialize to non-null string if no unique index found                 */
  2477.   if iid = 0 then
  2478.      colnames = '+'
  2479.  
  2480.   call querytb
  2481.  
  2482.   call putout '    '
  2483.   call putout tbname||full_tname            /* table name logged            */
  2484.   call putout tbtext||fname                 /* table file name logged       */
  2485.   if iid \= 0 then                          /* index name logged            */
  2486.      call putout indtext||strip(creator)||'.'||strip(name)
  2487.  
  2488.   if bias = 'OLD' then                      /* Dump Retained Row Report     */
  2489.      call retain_row
  2490.  
  2491.   /* Set options for ReConstruction Program */
  2492.   option_flag = 0                       /* default to No Force option       */
  2493.  
  2494.   /* Set up the Force Opt for the Inspection Program */
  2495.   if force_opt = 'YES' then
  2496.      option_flag = c2d(bitor(d2c(option_flag), '01'x))
  2497.  
  2498.  
  2499.   call ficlo 'REPORT'                       /* close the report file        */
  2500.   /* Initiate the ReConstruction phase */
  2501.   'cvp tarrecon ' fname iid colnames rptname option_flag
  2502.   recon_rc = rc                             /* return code of reconstruct.  */
  2503.  
  2504.  
  2505.   /* Display progress completion message for file */
  2506.   select
  2507.     when recon_rc = 0 then     /* No Rows Lost */
  2508.       dsp_rc = charout(,rcntxt || cr_lf)
  2509.     when recon_rc > 10 then    /* Errors encountered */
  2510.       dsp_rc = charout(,errtxt || cr_lf)
  2511.     otherwise                  /* Rows Lost */
  2512.       dsp_rc = charout(,lsttxt || cr_lf)
  2513.   end
  2514.  
  2515.   call filop 'REPORT'                       /* Open the Report File         */
  2516.   call handle_error recon_rc                /* handle error return          */
  2517.  
  2518.   drrname = substr(tmpfn,1,pos('.',tmpfn)) || 'DRR'
  2519.  
  2520.   if (recon_rc = 2) | (recon_rc = 0) then   /* if recon suceeds, rename .DEP*/
  2521.      'rename ' depname drrname
  2522.   else
  2523.      if recon_rc = 10 then                  /* if table lost completely     */
  2524.         do
  2525.             if (full_tname \= '...') then
  2526.                do
  2527.  
  2528.                    call dummy_desc          /* Create dummy Table Descr     */
  2529.                    drop_table = 'DROP TABLE '|| full_tname
  2530.                    call SQLEXEC 'EXECUTE IMMEDIATE :drop_table'
  2531.                    if (sqlca.sqlcode \= 0) then
  2532.                       call sqldump
  2533.  
  2534.                    /* Commit the Drop Table */
  2535.                    call SQLEXEC 'COMMIT'
  2536.                    if (sqlca.sqlcode \= 0) then
  2537.                       call sqldump
  2538.                end
  2539.             else
  2540.                'erase ' fname               /* table not in syscatalog      */
  2541.             'erase ' depname                /* erase .DEP file              */
  2542.          end
  2543.  
  2544. return
  2545.  
  2546.  
  2547. /******************************************************************
  2548. *  SUBROUTINE:   DUMMY_DESC                                       *
  2549. *                                                                 *
  2550. *  DESCRIPTIVE NAME: Create the Dummy Descriptor Record           *
  2551. *                                                                 *
  2552. *  DESCRIPTION: This routine gets control when an entire table    *
  2553. *               has been lost during repair.  Because of the      *
  2554. *               inability of Database Manager to drop a table     *
  2555. *               whose Table Descriptor Record has been lost       *
  2556. *               and unrecovered, this routine will create a       *
  2557. *               dummy table descriptor record in the slot         *
  2558. *               directory in order to proceed with dropping the   *
  2559. *               table.                                            *
  2560. *                                                                 *
  2561. *               In addition, the Slot Count of the page is        *
  2562. *               truncated to 4 since the dummy table descriptor   *
  2563. *               record is written in the slot directory itself.   *
  2564. *               This becomes important when the index has been    *
  2565. *               renamed previously such that Database Manager     *
  2566. *               will attempt to rebuild the index during the      *
  2567. *               Drop Table request.                               *
  2568. *                                                                 *
  2569. *               Note: The table has already been truncated to a   *
  2570. *                       single page during ReConstruction.  Again *
  2571. *                       this must be done because Database Mgr    *
  2572. *                       attempts to rebuild a renamed index       *
  2573. *                       during the Drop Table request.  No! This  *
  2574. *                       does not make sense.                      *
  2575. *                                                                 *
  2576. *               If the table cannot be dropped after this, there  *
  2577. *               is no hope.                                       *
  2578. *                                                                 *
  2579. *  INPUT: none                                                    *
  2580. *                                                                 *
  2581. *                                                                 *
  2582. *  OUTPUT: none                                                   *
  2583. *                                                                 *
  2584. ******************************************************************/
  2585.  
  2586. dummy_desc:
  2587.  
  2588. /* Open the table file */
  2589. rc = stream(fname, 'c', 'open')
  2590. if (rc = 'READY:') | (rc = 'READY') then
  2591.   do
  2592.     /* Define offset to Table Descriptor Record slot in Slot Directory */
  2593.     bpshdr_sz = 50       /* Size of BPS Header */
  2594.     dfhdr_sz = 20        /* Size of Data File Header */
  2595.     /* Calculate offset to Slot Count in Data File Header */
  2596.     dfhslot_off = bpshdr_sz + 1
  2597.     /* Calculate offset to Table Desc Rec slot in Slot Directory */
  2598.     dum_rec_off = bpshdr_sz + dfhdr_sz + (3*2) + 1
  2599.  
  2600.     /* Truncate the Slot Directory to 4 in Page 0 */
  2601.     new_slotcnt = 4
  2602.     rc = charout(fname, reverse(d2c(new_slotcnt,2)), dfhslot_off)
  2603.  
  2604.     /* Create dummy record header */
  2605.     dum_rec = '080000000400'x
  2606.  
  2607.     /* Write out dummy record header */
  2608.     rc = charout(fname, dum_rec, dum_rec_off)
  2609.  
  2610.     /* Close the table file to be dropped */
  2611.     rc = stream(fname, 'c', 'close')
  2612.  
  2613.   end
  2614.  
  2615. return
  2616.  
  2617.  
  2618. /******************************************************************
  2619. *  SUBROUTINE:   HANDLE_ERROR                                     *
  2620. *                                                                 *
  2621. *  DESCRIPTIVE NAME: handle the return code                       *
  2622. *                                                                 *
  2623. *  DESCRIPTION: This routine will handle the error code and decide*
  2624. *               what to do after that. It will also set the final *
  2625. *               return code of the TaRRR.                         *
  2626. *                                                                 *
  2627. *  INPUT: none                                                    *
  2628. *                                                                 *
  2629. *                                                                 *
  2630. *  OUTPUT: none                                                   *
  2631. *                                                                 *
  2632. ******************************************************************/
  2633.  
  2634. handle_error:
  2635.  
  2636.   parse arg rcode
  2637.  
  2638.   if rcode > 10 then
  2639.     do
  2640.       rcode = rcode - 255
  2641.       global_return = rcode       /* rcode = -12 handled here               */
  2642.       select
  2643.  
  2644.          when rcode = -2  then call errxit TAR0002N
  2645.  
  2646.          when rcode = -4  then call errxit TAR0004N
  2647.  
  2648.          when rcode = -6  then call errxit TAR0006N
  2649.  
  2650.          when rcode = -8  then call errxit TAR0008N
  2651.  
  2652.          when rcode = -10 then call errxit TAR0010N
  2653.  
  2654.          when rcode = -18 then call errxit TAR0018N
  2655.  
  2656.          otherwise
  2657.  
  2658.       end  /* end of select rcode                                           */
  2659.  
  2660.     end  /* return  rcode < 0                                               */
  2661.   else
  2662.     do
  2663.       /* Convert "Entire Table Lost" to the external "Data Rows Lost" rc    */
  2664.       if rcode = 10 then rcode = 2
  2665.  
  2666.       /* Preserve the Non-Fatal Return Code                                 */
  2667.       if (global_return = 0) & (rcode > 0) then
  2668.         global_return = rcode
  2669.       else
  2670.         do
  2671.           /* Determine if "Rows Lost" returned from ReConstruction and
  2672.                 "Known Problems Still Exist" returned from the Usable
  2673.                 Database Inspection                                         */
  2674.           if (global_return = 2) & (rcode = 4) then
  2675.             /* Return the combined "Rows Lost"/"Known Problems" rc          */
  2676.             global_return = 6
  2677.         end
  2678.     end
  2679.  
  2680.   return
  2681.  
  2682. /******************************************************************
  2683. *  SUBROUTINE:   GENERAL_HELP                                     *
  2684. *                                                                 *
  2685. *  DESCRIPTIVE NAME: TaRRR General Help                           *
  2686. *                                                                 *
  2687. *  DESCRIPTION: This routine displays the Help panels for the     *
  2688. *               TaRRR Tool.  This routine receives control        *
  2689. *               when the first input parameter is a "?".  A       *
  2690. *               brief description of the TaRRR and its            *
  2691. *               syntax is included in the Help panels.            *
  2692. *                                                                 *
  2693. *  INPUT: none                                                    *
  2694. *                                                                 *
  2695. *                                                                 *
  2696. *  OUTPUT: none                                                   *
  2697. *                                                                 *
  2698. ******************************************************************/
  2699.  
  2700. general_help:
  2701.  
  2702.   /* Display help panel */
  2703.   say "      "
  2704.   say ,
  2705.   "     ┌────────────────────────────────────────────────────────────┐       "
  2706.   say ,
  2707.   "     │         ┌────────────────────────────────────────┐         │       "
  2708.   say ,
  2709.   "     │         │        *****   T a R R R   *****       │         │       "
  2710.   say ,
  2711.   "     │         │             A  Utility  for            │         │       "
  2712.   say ,
  2713.   "     │         │   Table Repair/Recover/ReConstruction  │         │       "
  2714.   say ,
  2715.   "     │         └────────────────────────────────────────┘         │       "
  2716.   say ,
  2717.   "     │      ▀▀▀▀▀▀▀▀▀▀      ▀▀▀▀▀▀▀▀▀▀       ▀▀▀▀▀     ▀▀▀▀▀      │       "
  2718.   say ,
  2719.   "     │      ▀▀▀▀▀▀▀▀▀▀      ▀▀▀▀▀▀▀▀▀▀▀      ▀▀▀▀▀     ▀▀▀▀▀      │       "
  2720.   say ,
  2721.   "     │         ▀▀▀▀          ▀▀▀   ▀▀▀▀       ▀▀▀▀▀   ▀▀▀▀▀       │       "
  2722.   say ,
  2723.   "     │         ▀▀▀▀          ▀▀▀▀▀▀▀▀▀        ▀▀▀▀▀▀ ▀▀▀▀▀▀       │       "
  2724.   say ,
  2725.   "     │         ▀▀▀▀          ▀▀▀▀▀▀▀▀▀        ▀▀▀ ▀▀▀▀▀ ▀▀▀       │       "
  2726.   say ,
  2727.   "     │         ▀▀▀▀          ▀▀▀   ▀▀▀▀       ▀▀▀  ▀▀▀  ▀▀▀       │       "
  2728.   say ,
  2729.   "     │      ▀▀▀▀▀▀▀▀▀▀      ▀▀▀▀▀▀▀▀▀▀▀      ▀▀▀▀   ▀   ▀▀▀▀      │       "
  2730.   say ,
  2731.   "     │      ▀▀▀▀▀▀▀▀▀▀      ▀▀▀▀▀▀▀▀▀▀       ▀▀▀▀       ▀▀▀▀      │       "
  2732.   say ,
  2733.   "     └────────────────────────────────────────────────────────────┘       "
  2734.   say ,
  2735.   " ╔══════════════════════════════════════════════════════════════════════╗ "
  2736.   say ,
  2737.   " ║  The TaRRR Tool is a utility for the Repair, Recovery and            ║ "
  2738.   say ,
  2739.   " ║  ReConstruction of damaged tables in a database.  It provides the    ║ "
  2740.   say ,
  2741.   " ║  repair of damaged page fields, the retaining of existing records    ║ "
  2742.   say ,
  2743.   " ║  or the recovery from the Write-Ahead Log, and the generation of     ║ "
  2744.   say ,
  2745.   " ║  information in the report for page reconstruction.  The purpose of  ║ "
  2746.   say ,
  2747.   " ║  this tool is to make the database and its tables usable if possible.║ "
  2748.   say ,
  2749.   " ╚══════════════════════════════════════════════════════════════════════╝ "
  2750.   say "      "
  2751.   'pause'
  2752.   say "      "
  2753.   say ,
  2754.   "               Syntax:   TaRRR  [dbname] [/B:{OLD | NEW | NSPEC | NSPECX}]"
  2755.   say ,
  2756.   "                                [/T:fname]  [/P:page]                     "
  2757.   say ,
  2758.   "                                [/R:[[path]rptname[.ext]]]                "
  2759.   say ,
  2760.   "                                [/O:{YES|NO}]  [/I:{YES|NO}]              "
  2761.   say "      "
  2762.   say " where: "
  2763.   say ,
  2764.   "    [dbname]      is the alias name of the database containing the        "
  2765.   say ,
  2766.   "                                damaged table(s).                         "
  2767.   say "      "
  2768.   say ,
  2769.   "    [/B:{OLD|NEW|NSPEC|NSPECX}]  is the optional Repair Bias Option       "
  2770.   say ,
  2771.   "                                keyword specification.                    "
  2772.   say "      "
  2773.   say ,
  2774.   "    [/T:fname]    is the optional fully-qualified OS/2 filename of the    "
  2775.   say ,
  2776.   "                                damaged table.                            "
  2777.   say ,
  2778.   "    [/P:page]     is the optional damaged page number in the table file.  "
  2779.   say "      "
  2780.   say ,
  2781.   "    [/R:rptname]  is the OS/2 filename of the Report File.                "
  2782.   say "      "
  2783.   say ,
  2784.   "    [/O:{YES|NO}] is the Automatic ReOrg Option keyword specification.    "
  2785.   say ,
  2786.   "    [/I:{YES|NO}] is the Automatic Usable Database Inspection keyword     "
  2787.   say ,
  2788.   "                                specification.                            "
  2789.  
  2790.  
  2791.   return
  2792.