home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / db22fr.zip / SQLUEX01.EX5 < prev    next >
Text File  |  1992-11-06  |  46KB  |  1,056 lines

  1. /*************************************************************************/
  2. /*************************************************************************/
  3. /* SQLUEXIT                                                              */
  4. /*                                                                       */
  5. /*            566933603 COPYRIGHT IBM CORP. 1987, 1991                   */
  6. /*            LICENSED MATERIAL - PROGRAM PROPERTY OF IBM                */
  7. /*            Refer to Copyright Instructions Form Number G120-3083      */
  8. /*                                                                       */
  9. /*      This command file is provided as an sample of how to handle      */
  10. /*      exit requests from the IBM Database Manager to perform various   */
  11. /*      requests.  It may be modified to meet your particular needs.     */
  12. /*                                                                       */
  13. /*      For further information, see the IBM OS/2 Guide to Database      */
  14. /*      Manager.                                                         */
  15. /*                                                                       */
  16. /*************************************************************************/
  17.  
  18. signal on halt                          /* call HALT: routine on CTRL-BREAK */
  19. '@ECHO OFF'
  20. /******************************************************************************/
  21. /*                                  PROLOGUE                                  */
  22. /******************************************************************************/
  23. /******************************************************************************/
  24. /*                                                                            */
  25. /* SAMPLE NAME :  SQLUEX01.CMD                                                */
  26. /*                                                                            */
  27. /* PURPOSE :   This is a example using IBM Corporation's PMTAPE 2.0           */
  28. /*             software to manage files for Database Manager's Backup and     */
  29. /*             Restore utilities and to Archive and Retrieve Database Manager */
  30. /*             log files.                                                     */
  31. /*                                                                            */
  32. /*             This sample User Exit was developed using PMTAPE               */
  33. /*             software Version 2.0.                                          */
  34. /*                                                                            */
  35. /*             NOTE: This file must be renamed SQLUEXIT.CMD and located in    */
  36. /*                   PATH before it can be invoked by the Database Manager.   */
  37. /*                                                                            */
  38. /*             NOTE: Uncomment the "OPTIONS" line following this prologue     */
  39. /*                   for DBCS environments.                                   */
  40. /*                                                                            */
  41. /* OPTIONS:    (1) This sample provides a detailed audit trail of every       */
  42. /*                 call ( stored in a separate file for each function)        */
  43. /*                 including timestamp and parameters received (can           */
  44. /*                 optionally be disabled ).                                  */
  45. /*                                                                            */
  46. /************* (2) See the INIT procedure for details on configuration ********/
  47. /*                 options. IT IS ASSUMED THAT THE DATABASE MANAGER AND       */
  48. /*                 PMTAPE ARE INSTALLED ON C DRIVE. If not you can go to      */
  49. /*                 Default Configuration Values in INIT procedure and         */
  50. /*                 change it as required. The databases can be created   */
  51. /*                 on any drive.                                              */
  52. /*                                                                            */
  53. /*                                                                            */
  54. /*  Backup/Restore Notes:                                                     */
  55. /*                                                                            */
  56. /*              (1) The user must use this userexit program to backup         */
  57. /*                  the database and to restore the database. If the          */
  58. /*                  database is not backed up using this userexit program     */
  59. /*                  then the restore function will fail.                      */
  60. /*                                                                            */
  61. /*                                                                            */
  62. /*             (2) Each backup of a database requires two Backup Sets on the  */
  63. /*                 tape media.  One for the special dbname.UIF file and one   */
  64. /*                 for the actual database files.                             */
  65. /*                                                                            */
  66. /*                                                                            */
  67. /*             (3) It is possible to backup more than one version of the same   */
  68. /*                 database. If so you need to change the DATABASE.TPF file   */
  69. /*                for the RESTPROC so that it contains the name of the backup */
  70. /*                set you want to restore                                     */
  71. /*                                                                            */
  72. /*                                                                            */
  73. /*             (4) You can customize the DATABASE.TPF to run backup and       */
  74. /*                 restore to your desired specification.                     */
  75. /*                                                                            */
  76. /*                                                                            */
  77. /*             (5) If Archive and retrive options are to be used then user    */
  78. /*                 MUST set the User Exit and Log Retain options ON in        */
  79. /*                 configuration tool in the Database Manager.                                        */
  80. /*                                                                            */
  81. /*      Archiving Notes:                                                      */
  82. /*                                                                            */
  83. /*                 This example allows for "staging" of log files prior to    */
  84. /*                 calling PMTAPE.  Modify the "LOGS_TO_HOLD" configuration   */
  85. /*                 parameter in INIT procedure to contain the number of logs to be  */
  86. /*                 staged prior  to calling PMTAPE.  It should be noted that the            */
  87. /*                 LOGS_TO_HOLD parameter is on a Database Manager level,     */
  88. /*                 however, the individual logs are staged in subdirectories  */
  89. /*                 by database.                                               */
  90. /*                                                                            */
  91. /*                                                                            */
  92. /*                                                                            */
  93. /*      Retrieve Notes:                                                       */
  94. /*                                                                            */
  95. /*              To retrieve a database the user can call database rollforward */
  96. /*                                                                            */
  97. /*                                                                            */
  98. /*  OUTPUTS :  (1) Activity to the screen                                     */
  99. /*             (2) Optional activity to an audit file ("option".LOG)          */
  100. /*             (3) Error file ("option".ERR) on error conditions              */
  101. /*             (4) Staged log files                                           */
  102. /*                                                                            */
  103. /*                                                                            */
  104. /*  USAGE :                                                                   */
  105. /*                                                                            */
  106. /*        DATABASE MANAGER CALLS SQLUEXIT                                     */
  107. /*             SQLUEXIT  OPTION  PARM1 PARM2 PARM3 PARM4 ╒PARM5■              */
  108. /*                                                                            */
  109. /*             where :   OPTION = 'ARCHIVE'  ( save a log file )              */
  110. /*                                'RETRIEVE' ( get a log file )               */
  111. /*                                'BACKUP'   ( backup database files )        */
  112. /*                                'RESTORE'  ( restore database files )       */
  113. /*                                                                            */
  114. /******************************************************************************/
  115. /****************************************************************************/
  116.  
  117. /* OPTIONS "ETMODE" "EXMODE" */           /* Uncomment for DBCS environment */
  118. /* TRACE ?R */                             /* Uncomment to trace batch file */
  119.  
  120. /************************/
  121. /* Get input parameters         */
  122. /************************/
  123.  
  124.  parse upper arg OPT PARM1 PARM2 PARM3 PARM4 PARM5
  125.  
  126.  PARMS = '    PARAMETERS ==> '                /* Log the parameters received */
  127.  PARMS = PARMS ||OPT' 'PARM1' 'PARM2,
  128.               ' 'PARM3' 'PARM4' 'PARM5
  129. /***************************************************************************/
  130. /*************************** INITIALIZE VARIABLES *****************************/
  131. /***************************************************************************/
  132.  
  133.  DB_DRIVE  = strip(PARM1)                 /* ex.  C:       */
  134.  call INIT     /* Initialize User defined variables and configuration parms */
  135.  
  136. /****************************************************************************/
  137. /***************************** SQLUEXIT MAIN BEGIN ***************************/
  138. /****************************************************************************/
  139.  
  140. /***********************************************/
  141. /* Register this call to the SQLUEXIT log file                     */
  142. /***********************************************/
  143.  
  144.  if AUDIT = 'Y' then                                 /* Audit trail enabled? */
  145.  do
  146.   if stream(UEXIT_LOG, 'c', 'query exists') = '' then        /* No log file */
  147.     do
  148.       cfg_line = 'Initial Configuration: ',   /* Make current configuration */
  149.                   'Audit <'AUDIT'> ',         /* the first line in the file */
  150.                   'Number of log files to stage <'LOGS_TO_HOLD'>'
  151.       call lineout UEXIT_LOG, cfg_line
  152.     end
  153.  
  154.   call lineout UEXIT_LOG, ' '
  155.   call lineout UEXIT_LOG, DT             /* Write timestamp to the log file */
  156.   call lineout UEXIT_LOG, ' '
  157.   call lineout UEXIT_LOG, PARMS             /* Write parameters to log file */
  158.   call lineout UEXIT_LOG, ' '
  159.  end
  160.  
  161.  
  162. /*******************************************/
  163. /* Jump to the function requested by caller                 */
  164. /*******************************************/
  165.  
  166. select
  167.   when OPT = 'ARCHIVE'  then signal ARCHPROC                 /* Archive logs */
  168.   when OPT = 'RETRIEVE' then signal RETVPROC                /* Retrieve logs */
  169.   when OPT = 'BACKUP'   then signal BUPROC                /* Backup database */
  170.   when OPT = 'RESTORE'  then signal RESTPROC              /* Restore database */
  171.   OTHERWISE do                                                                   /* Unknown option */
  172.      ELINE = 'The option "'OPT'" is not valid.'
  173.      sqluexitrc = IBM_RC.PARM
  174.      signal FINISH
  175.   end
  176. end
  177. /****************************** END SQLUEXIT MAIN ***************************/
  178.  
  179.  
  180. /***************************************************************************/
  181. /******************************* BACKUP DATABASE ***************************/
  182. /***************************************************************************/
  183. /*                                                                            */
  184. /*        BACKUP sample of Database Manager call to the user exit:            */
  185. /*                                                                            */
  186. /* SQLUEXIT BACKUP C: BRNSDDB1 C:\SQLDBDIR\SQL00001.BKP BRNSDDB1-684686581 1  */
  187. /*                                                                            */
  188. /*           Requests SQLUEXIT to backup the database files listed in the     */
  189. /*           response file C:\SQLDBDIR\SQL00001.BKP for database BRNSDDB1     */
  190. /*           which is located on drive C:.  The mode is '1' which indicates   */
  191. /*           this is the first (of two) calls required to complete the        */
  192. /*           backup process. Label BRNSDDB1-684686581 (database-timestamp) is */
  193. /*           provided to SQLUEXIT to assist in backup management by SQLUEXIT  */
  194. /*           if desired.                                                      */
  195. /*                                                                            */
  196. /****************************************************************************/
  197. BUPROC:
  198.  
  199.  
  200.   call checkparms              /* Check that the input parameters are valid */
  201.  
  202. /*********************************************/
  203. /* Clear surrounding spaces from input parms         */
  204. /*********************************************/
  205.  
  206.   DB_DRIVE  = strip(PARM1)                  /* ex.  C                       */
  207.   DB_NAME   = strip(PARM2)                 /* ex.  BRNSDDB1                 */
  208.   RESP_FILE = strip(PARM3)                 /* ex.  C:\SQLDBDIR\SQL00001.BKP */
  209.   LABEL     = strip(PARM4)                     /* ex.  BRNSDDB1-684686581       */
  210.   MODE      = strip(PARM5)                    /* ex.  1                       */
  211. /*****************************************************/
  212. /* To create a .tpf file from PARM3 which will be used by               */
  213. /*  PMTAPE to backup the database.                                      */
  214. /*****************************************************/
  215.  tpffile=PMT_DIR'\pmtape\database.tpf'
  216.  'ERASE 'tpffile' 1>NUL 2>NUL'
  217.           /* If the file being erased doesn't exist then no error is reported */
  218.  rsplst = PARM3
  219.  call LINEOUT tpffile,"!BACKUP",1
  220.  
  221. /******************/
  222. /* The backup set name is given the same name as the database name      */
  223. /* so that when restore makes a call to restore the database the backup */
  224. /* set name will be the same as the database name                       */
  225. /*******************/
  226.   call LINEOUT tpffile,'/w scnf /l 'PMT_DIR'\PMTAPE\BACKLOG xi /m /n "'DB_NAME'"  /r /c 0 /g '
  227.  numlin = LINES(rsplst)       /* LINES( ) will return 0 end of file is reached */
  228.  DO WHILE (numlin >= 1)
  229.      inline = LINEIN(rsplst)
  230.        call LINEOUT tpffile,"/b /b rhs /q /S"  inline
  231.         numlin = LINES(rsplst)
  232.  END
  233.  call LINEOUT tpffile                    /* close the file */
  234. /***********************************************************/
  235.  
  236. /****************************************************/
  237. /* Make call to PMTAPE  to backup file(s)                              */
  238. /****************************************************/
  239.   ifile = PMT_DIR"\PMTAPE\BACKLOG"
  240.   'ERASE 'ifile
  241.   'PMTAPE 'PMT_DIR'\PMTAPE\DATABASE.TPF'
  242.    /************************/
  243. call verify_backup
  244. call checkrc                              /* Check return code            */
  245.  
  246. /********************************************************/
  247. /*    ERASING INDEX FILE                                                     */
  248. /*********************************************************/
  249. /*    The index file contains information about the backup set name         */
  250. /*     for all the files on PMTAPE. Every time a certain database is        */
  251. /*     backed up the lines containing the info about that database          */
  252. /*      are deleted.                                                        */
  253. /*************************************************************/
  254.  
  255.  indxfile = DBM_DIR'\PMTINDEX.DAT'
  256.  if LINES(indxfile) = 1 then
  257.  do
  258.   tempfile = DBM_DIR'\TEMPOUT.DAT'
  259.   DO WHILE (LINES(indxfile)=1)
  260.    string=LINEIN(indxfile)
  261.    lastline = string
  262.    tempname=SUBSTR(string,21)
  263.    slash_loc=POS('\',tempname)
  264.    dbname=LEFT(tempname,slash_loc-1)
  265.    if dbname<>DB_NAME then
  266.     call lineout tempfile, string
  267.  end    /* do */
  268.  call LINEOUT tempfile,lastline
  269.  call lineout indxfile
  270.  call lineout tempfile
  271.  'ERASE 'indxfile
  272.  indxfile = DBM_DIR'\PMTINDEX.DAT'
  273.  'COPY 'tempfile' 'indxfile
  274.  'ERASE 'tempfile
  275. end
  276. /***************************************************************************/
  277.  
  278.   signal FINISH                                                /* Finish up */
  279. /***************************** END BACKUP DATABASE *************************/
  280. /****************************************************************************/
  281. RESTPROC:
  282.  
  283.  tpffile=PMT_DIR'\PMTAPE\DATABASE.tpf'
  284.  /* If the file being erased does not exist then no error is reported */
  285.  'ERASE 'tpffile' 1>NUL 2>NUL'
  286.   call checkparms              /* Check that the input parameters are valid */
  287.  
  288. /*********************************************/
  289. /* Clear surrounding spaces from input parms         */
  290. /*********************************************/
  291.  
  292.   DB_DRIVE  = strip(PARM1)                 /* ex.  C:                       */
  293.   DB_NAME   = strip(PARM2)                 /* ex.  BRNSDDB1                 */
  294.   RESP_FILE = strip(PARM3)                 /* ex.  C:\SQLDBDIR\SQL00001.BKP */
  295.   REST_DIR  = strip(PARM4)                 /* ex.  BRNSDDB1-684686581       */
  296.   MODE      = strip(PARM5)                 /* ex.  1                        */
  297.  
  298. /************************************************************/
  299. /* To create a .tpf file from PARM3 which will be used by                  */
  300. /*     PMTAPE to backup the database.                                      */
  301. /************************************************************/
  302.  rsplst = PARM3
  303.  call LINEOUT tpffile,"!Restore",1
  304.  call LINEOUT tpffile,"/w socnf /m /t "DB_DRIVE""REST_DIR"  /p 2 /k 0 /o 2"
  305.  call LINEOUT tpffile,"/b /b rhs /q"
  306.  if MODE = 1 then
  307.   call LINEOUT tpffile,'/s' '"'DB_NAME"\*"'"'
  308.  else
  309.   call LINEOUT tpffile,'/s' '"'DB_NAME"-2\*"'"'
  310.  call LINEOUT tpffile
  311.  /***************************************************/
  312. /* Make call to PMTAPE to backup file(s)                              */
  313. /****************************************************/
  314.  if MODE = 1 then
  315.    'PMTAPE 'PMT_DIR'\PMTAPE\DATABASE.TPF'
  316.  else  'PMTAPE 'PMT_DIR'\PMTAPE\DATABASE.TPF'
  317.    call checkrc                              /* Check return code            */
  318.  signal FINISH                                                /* Finish up */
  319. /***************************** END RESTORE DATABASE ************************/
  320.  
  321.  
  322. /****************************************************************************/
  323. /***************************** ARCHIVE A LOG FILE *****************************/
  324. /****************************************************************************/
  325. ARCHPROC:
  326. /***********************************************/
  327. /*  check that the input parameters are valid            */
  328. /***********************************************/
  329.    call checkparms
  330.  
  331. /**************************************/
  332. /*  clean off any surrounding spaces       */
  333. /**************************************/
  334.  
  335.   DB_DRIVE = left(strip(PARM1), 1)                  /* Throw away the colon */
  336.   DB_NAME  = strip(PARM2)
  337.   LOG_PATH = strip(PARM3)
  338.   LOG_FILE = strip(PARM4)
  339.  
  340. /******************************************************/
  341. /*  Modify LOG_PATH to contain the full log file name              */
  342. /******************************************************/
  343.  
  344. LOG_PATH = LOG_PATH||LOG_FILE
  345.  
  346. /*********************************************************/
  347. /* Check to see if the log file exists.  If not, it is                       */
  348. /* assumed to have already been archived on a previous                       */
  349. /* request.  Return IBM_RC.OK                                                */
  350. /*********************************************************/
  351.   if stream(LOG_PATH, c, 'query exists') = '' then
  352.     do
  353.       sqluexitrc = IBM_RC.OK
  354.       ELINE = 'The file 'LOG_PATH' was assumed to be previously archived'
  355.       signal FINISH
  356.     end
  357.  
  358. /******************************************************/
  359. /* Create full path: e.g. c:\userexit\log_hold\testdb                      */
  360. /******************************************************/
  361.  
  362.  ARCH_PATH = LOG_HOLD'\'DB_NAME
  363.                            /* Make sure the directory exists if not create it */
  364.  call verify_path(ARCH_PATH)
  365. /*****************************************/
  366. /* Copy the log file to the staging path                 */
  367. /*****************************************/
  368.  
  369.   'xcopy 'LOG_PATH' 'ARCH_PATH
  370.  
  371.   call check_xcopyrc                             /* Check the rc from XCOPY */
  372.   if sqluexitrc <> 0 then
  373.     signal FINISH
  374.  
  375. /****************************************/
  376. /* Add the new file to the archive list                        */
  377. /****************************************/
  378.  
  379.   lf_name = ARCH_PATH'\'LOG_FILE
  380.   call lineout UEXIT_LST, lf_name
  381.   call stream UEXIT_LST, c, 'close'
  382. /*************************************/
  383. /*   Get the Backup set name of PMTAPE from  */
  384. /*    the index file.                        */
  385. /**************************************/
  386.   indxfile = DBM_DIR"\PMTINDEX.DAT"
  387.  
  388.   if (LINES(indxfile) =0) then do
  389.     next_tape_dr = 1
  390.     call LINEOUT indxfile, "/* index file for PMTAPE log archives */",1
  391.     call LINEOUT indxfile," 0 "
  392.     call LINEOUT indxfile
  393.   end
  394.   else do
  395.     DO WHILE ((LINES(indxfile) =1))
  396.     istring=LINEIN(indxfile)
  397.   end
  398.     call LINEOUT indxfile
  399.     blank_loc =POS(' ',istring)
  400.     tape_directory = SUBSTR(istring,blank_loc+1)
  401.     next_tape_dr = tape_directory + 1
  402. end
  403.  
  404. /*******************************************************/
  405. /* Check to see if the file containing the number of                     */
  406. /* log files held exists.  If it does, read the number                   */
  407. /* held and bump it by one, otherwise, assume this is                    */
  408. /* the first log file to be staged and create the tpf file.              */
  409. /*******************************************************/
  410.  
  411.  
  412.   if stream(NUM_LOGS_HELD, c, 'query exists') = '' then
  413.   do
  414.     /************/                                                                    tpffile=PMT_DIR'\pmtape\DATABASE.tpf'
  415.     /* To make sure that the file pointer is at the beginning of the file */
  416. 'ERASE 'tpffile' 1>NUL 2>NUL'
  417.     /* and create the TPF file. User can add desired options to the .tpf file */
  418.        call LINEOUT tpffile,"!Backup",1
  419.     /*************/                                                                     call LINEOUT tpffile,'/w sc /l BACKUP.LOG /m /n' '"'next_tape_dr'"' '/r /c 0 /g'
  420.     call LINEOUT tpffile,'/b /b rhs /s' '"'lf_name'"'
  421.     held_logs = 1
  422.  
  423.     tempfile = DBM_DIR'\SQLLIB\TEMP.FIL'
  424.     'ERASE ' tempfile '1>NUL 2>NUL'
  425.     afile = lf_name
  426.     call LINEOUT tempfile, afile next_tape_dr, 1
  427.     call LINEOUT tempfile
  428.   end
  429.   else
  430.       do
  431.          tpffile=PMT_DIR'\pmtape\DATABASE.tpf'
  432.          call LINEOUT tpffile,'/b /b rhs /s' '"'lf_name'"'
  433.          rsp_line = linein(NUM_LOGS_HELD)                /* Read the record */
  434.          held_logs = (substr(rsp_line,1,1)) +1  /*Bump the # logs held by 1 */
  435.                       /* rexx exec to add a single line to an existing file */
  436.          afile = lf_name
  437.          tempfile =DBM_DIR'\SQLLIB\TEMP.FIL'
  438.          call LINEOUT tempfile, afile next_tape_dr
  439.          call LINEOUT tempfile
  440.      end
  441.           /* Call PMTAPE when no. of archived files is equal to logs to hold */
  442.  if held_logs >= LOGS_TO_HOLD then
  443.  do
  444.   tempfile = DBM_DIR'\SQLLIB\TEMP.FIL'
  445.   'COPY 'DBM_DIR'\PMTINDEX.DAT + 'tempfile '1>NUL'
  446.  
  447.   'ERASE 'tempfile' 1>NUL 2>NUL'
  448.   call LINEOUT tpffile
  449.   call LINEOUT NUM_LOGS_HELD
  450.   'pmtape 'PMT_DIR'\pmtape\DATABASE.tpf'
  451.   'ERASE ' NUM_LOGS_HELD' 1>NUL 2>NUL'
  452.   erase_line = linein(UEXIT_LST, 1)
  453.   do while LINES(UEXIT_LST) > 0
  454.       'ERASE 'erase_line' 1>NUL 2>NUL'
  455.        erase_line = linein(UEXIT_LST)
  456.   end /* do */
  457.   'ERASE 'erase_line' 1>NUL 2>NUL'
  458.   call stream UEXIT_LST, c, 'close'
  459.   'ERASE 'UEXIT_LST' 1>NUL 2>NUL'
  460.   end
  461.   else
  462.   do
  463.     call lineout NUM_LOGS_HELD, held_logs, 1            /* Write out logs held*/
  464.     call stream NUM_LOGS_HELD, c, 'close'                   /* Close the file */
  465.   end
  466.   signal FINISH
  467. /************************************************/
  468.  
  469. /***************************** RETRIEVE A LOG FILE ****************************/
  470. /****************************************************************************/
  471. RETVPROC:
  472.  
  473. /***********************************************/
  474. /*  check that the input parameters are valid                    */
  475. /***********************************************/
  476.     call checkparms
  477.  
  478. /**************************************/
  479. /*  clean off any surrounding spaces               */
  480. /**************************************/
  481.  
  482.   DB_DRIVE = left(strip(PARM1), 1)                  /* Throw away the colon */
  483.   DB_NAME  = strip(PARM2)
  484.   LOG_PATH = strip(PARM3)
  485.   LOG_FILE = strip(PARM4)
  486.  
  487. /****************************************************/
  488. /* Create the well known staging path for log files                    */
  489. /****************************************************/
  490.  
  491.   ARCH_PATH = LOG_HOLD'\'DB_NAME
  492.  
  493.   call verify_path(ARCH_PATH)
  494.   slash_loc =POS('\',ARCH_PATH)
  495.   A_PATH = SUBSTR(ARCH_PATH,slash_loc+1)
  496.  
  497.                /* creating temporary storage for retrieving info from tape */
  498.  
  499.   RTRV_DIR = DB_DRIVE':\TAPEDIR'
  500.   'MD 'RTRV_DIR' 1>NUL 2>NUL'
  501.  
  502. /*********************************************************/
  503. /* If the requested log file exists in staging area or temporary storage     */
  504. /* copy it to the current log path.  Otherwise, call the                     */
  505. /* tape_retrieve procedure to get the file from tape.                        */
  506. /*********************************************************/
  507.  
  508.   if stream(ARCH_PATH'\'LOG_FILE, c, 'query exists') <> '' then
  509.   do
  510.      'XCOPY 'ARCH_PATH'\'LOG_FILE' 'LOG_PATH'*.*'
  511.  
  512.      call check_xcopyrc                          /* Check the rc from XCOPY */
  513.      if sqluexitrc <> 0 then
  514.        signal FINISH
  515.   end
  516.  
  517.  
  518.   else do
  519. /*********************************************************/
  520. /* If the requested log file exists in temporary storage area,               */
  521. /* copy it to the current log path.  Otherwise, call the                     */
  522. /* tape_retrieve procedure to get the file from tape.                        */
  523. /*********************************************************/
  524.  
  525.  
  526.   if stream(RTRV_DIR'\'A_PATH'\'LOG_FILE, c, 'query exists') <> '' then
  527.   do
  528.      'XCOPY 'RTRV_DIR'\'A_PATH'\'LOG_FILE' 'LOG_PATH'*.*'
  529.  
  530.      call check_xcopyrc                          /* Check the rc from XCOPY */
  531.      if sqluexitrc <> 0 then
  532.        signal FINISH
  533.   end
  534.  
  535.   else
  536.    call tape_retrieve
  537.   end
  538.   signal FINISH
  539.  
  540.  
  541. /*************************** END RETRIEVE A LOG FILE *************************/
  542. /*************************** VERIFY BACKUP PROCEDURE *************************/
  543. /************************/
  544. verify_backup:
  545.  
  546. /* If the backup fails call PMTAPE again till it is successful */
  547. count = 1
  548. if (LINES(ifile) =0) then do
  549.  say "no log file exists"
  550.  say "return to caller with error"
  551.  exit
  552. end
  553. DO WHILE   (count < 9 )
  554. count = count + 1
  555. DO WHILE (LINES(ifile) =1)
  556.        istring=LINEIN(ifile)
  557.        equals=LEFT(istring,1)
  558.        if equals = '=' then do
  559.            istring=LINEIN(ifile)
  560.            istring=LINEIN(ifile)
  561.            equals=LEFT(istring,1)
  562.                     /* Check log file for unsuccessful */
  563.                     /* backup file if does call PMTAPE */
  564.            if equals <> ' ' then do
  565.           call LINEOUT (ifile)
  566. say "Error in backup"
  567. pull hi
  568.          'ERASE 'ifile
  569.                     'PMTAPE 'PMT_DIR'\PMTAPE\DATABASE.TPF'
  570.            end
  571.            else do
  572.               istring=LINEIN(ifile)
  573.               istring=LINEIN(ifile)
  574.               equals=LEFT(istring,1)
  575.                     /* Check log file for successful */
  576.                     /* backup file if none exist call PMTAPE */
  577.               if equals = '=' then do
  578.          call LINEOUT (ifile)
  579. say "Error in backup"
  580. pull hi
  581.          'ERASE 'ifile
  582.                     'PMTAPE 'PMT_DIR'\PMTAPE\DATABASE.TPF'
  583.               end
  584.     else exit
  585.            end
  586.   end
  587. end
  588. call LINEOUT (ifile)
  589. end
  590. return 0
  591.  
  592. /*************************** END VERIFY BACKUP PROCEDURE *************************/
  593.  
  594.  
  595. /**************************** CHECKPARMS PROCEDURE ***********************/
  596. /* Routine for verifying that all parameters passed into SQLUEXIT have some  */
  597. /* value.  PARM5 is required only for Backup and Restore.                    */
  598. /***************************************************************************/
  599. checkparms:
  600.  
  601.   if( ((ACTION = 'RESTORE') | (ACTION = 'BACKUP')) & PARM5 = ''),
  602.      | (PARM1 = '' | PARM2 = '' | PARM3 = '' | PARM4 = '')
  603.     then
  604.       do
  605.         ELINE = 'One or more input parameters are null.'
  606.         sqluexitrc = IBM_RC.PARM
  607.         signal FINISH
  608.       end
  609.  
  610. return 0
  611. /******************************* END CHECKPARMS ****************************/
  612.  
  613.  
  614. /******************************* INIT PROCEDURE *****************************/
  615. /* Routine for initializing user defined variables and configuration        */
  616. /* parameters.                                                              */
  617. /****************************************************************************/
  618. INIT:
  619.  
  620. /*************************/
  621. /* TIMESTAMP INFORMATION */
  622. /*************************/
  623. ODATE = DATE()                                              /* Current date */
  624. OTIME = TIME()                                              /* Current time */
  625. DT    = '*** 'ODATE', 'OTIME
  626.  
  627.  
  628. /********************************/
  629. /* DEFAULT CONFIGURATION VALUES */
  630. /********************************/
  631. AUDIT       = 'Y'                         /* Log user exit calls by default */
  632. LOGS_TO_HOLD = 9   /* Number of archived logs to hold prior to calling PMTAPE */
  633. PMT_DIR = 'C:'     /* The drive where PMTAPE is located */
  634. DBM_DIR="C:"       /* The drive where Database Manager is located */
  635.  
  636.  
  637. /**************************/
  638. /* USER DEFINED VARIABLES */
  639. /**************************/
  640. EXITDIR = DB_DRIVE'\USEREXIT'
  641. LOG_HOLD = EXITDIR'\LOGHOLD'                  /* Staging area for log files */
  642. UEXIT_LOG = EXITDIR'\'OPT'.LOG'                           /* Audit log file */
  643. UEXIT_ERR = EXITDIR'\'OPT'.ERR'                      /* SQLUEXIT error file */
  644. UEXIT_LST = EXITDIR'\EXIT.LST'         /* FILE containing list of log files */
  645.                                        /* to archive */
  646. RETRIEVE_LST = EXITDIR'\RETRIEVE.LST'  /* FILE containing list of log files */
  647.                                        /* to retrieve */
  648. REDIRECT_FILE = EXITDIR'\REDIRECT.LST'           /* PMTAPE redirection file */
  649. NUM_LOGS_HELD = EXITDIR'\STAGED.LST'  /*File containing # archived log files*/
  650.                                      /* currently held. */
  651. ARCH_PATH = ''              /* Complete path name to copy log files to/from */
  652.  
  653. /*****************/
  654. /* RETURN CODES */
  655. /****************/
  656. IBM_RC.OK = 0                                                 /* SUCCESSFUL */
  657.  
  658. IBM_RC.RES = 4                                   /* RESOURCE ERROR OCCURRED */
  659. IBM_RC.OPATTN = 8                         /* OPERATOR INTERVENTION REQUIRED */
  660. IBM_RC.HARDWARE = 12                             /* HARDWARE ERROR OCCURRED */
  661. IBM_RC.DEFECT = 16               /* DEFECT/CONFIGURATION/INSTALLATION ERROR */
  662. IBM_RC.PARM = 20                              /* INVALID PARAMETER RECEIVED */
  663. IBM_RC.NOTFOUND = 24                          /* REQUIRED FILE(s) NOT FOUND */
  664. IBM_RC.UNKNOWN = 28                               /* UNKNOWN ERROR OCCURRED */
  665. IBM_RC.OPCAN = 32                                     /* OPERATOR CANCELLED */
  666.  
  667. sqluexitrc = IBM_RC.OK            /* VARIABLE USED TO PASS BACK RETURN CODE */
  668.  
  669. /*************************************/
  670. /* Make sure exit directory exists               */
  671. /*************************************/
  672.  
  673. call verify_path(EXITDIR)                 /* Path exists?/If not, create it */
  674. VERIFY_DIR = 'TRUE'
  675.  
  676. ELINE = ''                                                    /* Error text */
  677.  
  678. return 0
  679. /********************************** END INIT *********************************/
  680.  
  681.  
  682. /**************************** VERIFY_PATH PROCEDURE ************************/
  683. /* Verifies that the given path exists.  If not, it is created.            */
  684. /****************************************************************************/
  685. verify_path:
  686. arg CHK_PATH
  687.  
  688. curdir = directory()                           /* Save current directory  */
  689.  
  690. /***************************************************************/
  691. /* Separate drive from path and save the remainder of the path               */
  692. /***************************************************************/
  693.  
  694.   parse value CHK_PATH with drive '\' path_remain
  695.  
  696. /*****************************************/
  697. /* Break down path by subdirectory names                 */
  698. /*****************************************/
  699.  
  700.   i = 1
  701.   do while path_remain <> ''
  702.     parse value path_remain with path.i '\' path_remain
  703.     i = i + 1                                    /* Subdirectory name index */
  704.   end
  705.  
  706. /**********************************************************************/
  707. /* Rebuild the path one subdirectory at a time checking to see if the      */
  708. /* path exist and, if not, create it.                                      */
  709. /**********************************************************************/
  710.  
  711.   build_path = drive         /* Build path back up starting at drive letter */
  712.   j = 1
  713.   do while j < i
  714.     build_path = build_path'\'path.j          /* Add a subdirectory to path */
  715.  
  716.     newdir = directory( build_path )       /* See if the path already exist */
  717.     if( newdir <> build_path ) then do
  718.       md_var = 'MKDIR 'build_path
  719.       address CMD md_var                     /* Let OS/2 make the directory */
  720.       if (rc <> 0) then do
  721.         ELINE = md_var'   *** FAILED, <'rc'>'
  722.         sqluexitrc = IBM_RC.UNKNOWN
  723.         signal FINISH
  724.       end
  725.     end
  726.  
  727.     j = j + 1                               /* Bump subdirectory name index */
  728.   end
  729.  
  730.   call directory curdir                 /* Return to the original directory */
  731.  
  732. return 0
  733. /******************************* END VERIFY_PATH ****************************/
  734.  
  735.  
  736. /****************************** CHECKRC PROCEDURE**************************/
  737. /* Check the return code from the PMTAPE Software and map to the            */
  738. /* expected DBM return codes.                                               */
  739. /****************************************************************************/
  740. checkrc:
  741.  
  742.  pmtape_rc = rc
  743.  Select
  744.    when pmtape_rc = 0 then do                                  /* Successful */
  745.      sqluexitrc = IBM_RC.OK;
  746.      return;
  747.    end
  748.    OTHERWISE do                                            /* UNKNOWN ERROR */
  749.      ELINE= 'PMTAPE software returned ERROR <'pmtape_rc'>'
  750.      sqluexitrc = IBM_RC.UNKNOWN;
  751.      return;
  752.    end
  753.  end
  754.  
  755. return
  756. /**************************** END CHECKRC PROCEDURE ***********************/
  757.  
  758.  
  759. /*************************** CHECK_XCOPYRC PROCEDURE *********************/
  760. /* Check the return code from OS/2's XCOPY command and map to the expected  */
  761. /* DBM return codes.                                                                                                  */
  762. /****************************************************************************/
  763. check_xcopyrc:
  764.  
  765.  os2_rc = rc
  766.  
  767.  Select
  768.    when os2_rc = 0 then do                                    /* Successful */
  769.      sqluexitrc = IBM_RC.OK;
  770.      return;
  771.    end
  772.    when os2_rc = 1 then do
  773.      ELINE= 'OS/2 XCOPY ERROR <1>: No files found to Backup or Restore'
  774.      sqluexitrc = IBM_RC.NOTFOUND;
  775.      return;
  776.    end
  777.    when os2_rc = 2 then do
  778.      ELINE= 'OS/2 XCOPY ERROR <2>: Busy files not Backed up or Restored'
  779.      sqluexitrc = IBM_RC.UNKNOWN;
  780.      return;
  781.    end
  782.    when os2_rc = 3 then do
  783.      ELINE= 'OS/2 XCOPY ERROR <3>: Command Terminated by user'
  784.      sqluexitrc = IBM_RC.OPCAN;
  785.      return;
  786.    end
  787.    when os2_rc = 4 then do
  788.      ELINE= 'OS/2 XCOPY ERROR <4>: Command Terminated due to error'
  789.      sqluexitrc = IBM_RC.UNKNOWN;
  790.      return;
  791.    end
  792.    OTHERWISE do                                            /* Unknown error */
  793.      ELINE= 'OS/2 XCOPY command returned ERROR <'os2_rc'>'
  794.      sqluexitrc = IBM_RC.UNKNOWN;
  795.      return;
  796.    end
  797.  end
  798.  
  799. return
  800. /************************* END CHECK_XCOPYRC PROCEDURE *******************/
  801.  
  802.  
  803. /************************ REMOVE TEMP STORAGE PROCEDURE ******************/
  804. /*************************************************************************/
  805. /*  Procedure to remove temporary storage directory                      */
  806. /*************************************************************************/
  807.  
  808. rmvdirs:
  809.  
  810. newdir = directory(DB_DRIVE":\TAPEDIR\USEREXIT")
  811. if newdir = DB_DRIVE":\TAPEDIR\USEREXIT" then
  812. do
  813.                                        /* Save DIR command output in a file  */
  814.   'DIR 'DB_DRIVE':\TAPEDIR\USEREXIT\LOGHOLD>'DBM_DIR'\SQLLIB\REMOVE'
  815.   dirfile = DBM_DIR"\SQLLIB\REMOVE"
  816.   if (LINES(dirfile) =0) then do
  817.       say "no index file exists"
  818.       exit
  819.    end
  820.                           /* Skip lines till you get to the directory names  */
  821.     DO 7
  822.        istring=LINEIN(dirfile)
  823.      end
  824.      empty=0
  825.      istring=LINEIN(dirfile)
  826.                                                 /* Get the directory name */
  827.      blank_loc =POS(' ',istring)
  828.      tdir = LEFT(istring,blank_loc-1)
  829.     if tdir = "" then
  830.     do
  831.        empty = 1
  832.     end
  833.     else do                                     /* Erase the directory */
  834.        'CD 'DB_DRIVE':\TAPEDIR\USEREXIT\LOGHOLD\'tdir
  835.        'DIR'
  836.        'ERASE *.LOG'
  837.        'CD ..'
  838.        'RD 'tdir
  839.     end /* else */
  840.                                    /* Continue deleting subdirectories until */
  841.                                    /* all are deleted                        */
  842.  
  843.     DO WHILE((LINES(dirfile) =1) & (empty=0))
  844.  
  845.         istring=LINEIN(dirfile)
  846.  
  847.         blank_loc =POS(' ',istring)
  848.         tdir = LEFT(istring,blank_loc-1)
  849.         if tdir = "" then
  850.             empty = 1
  851.        else do
  852.          'CD 'DB_DRIVE':\TAPEDIR\USEREXIT\LOGHOLD\'tdir
  853.          'DIR'
  854.          'ERASE *.LOG'
  855.          'CD ..'
  856.          'RD 'tdir
  857.        end /* else */
  858.      end /* while */
  859.       'CD ..'
  860.       'RD LOGHOLD'
  861.       'CD ..'
  862.       'RD USEREXIT'
  863.       'CD ..'
  864.       'RD TAPEDIR'
  865.    end /* if */
  866.  
  867.    return 0
  868.  
  869. /****************************************************************************/
  870. /******************** END REM TEMP STORAGE PROCEDURE ************************/
  871.  
  872.  
  873. /*************************** TAPE_RETRIEVE PROCEDURE ***********************/
  874. /* Call PMTAPE to retrieve the requested log file from tape.                */
  875. /****************************************************************************/
  876. tape_retrieve:
  877.  
  878.  
  879. /********************************/
  880. /*  Clear the RETRIEVE_LST file            */
  881. /********************************/
  882.  
  883.   'ERASE 'RETRIEVE_LST' 1>NUL 2>NUL'
  884.  
  885. /*****************************************/
  886. /* Create a new list file to call PMTAPE                 */
  887. /*****************************************/
  888.  
  889.   lf_name = ARCH_PATH'\'LOG_FILE
  890.   call lineout RETRIEVE_LST, lf_name
  891.   call stream RETRIEVE_LST, c, 'close'
  892.  
  893. /*****************************************/
  894. /* Build the redirection file for PMTAPE */
  895. /* This allows us to restore the file to */
  896. /* a path other than the origin.         */
  897. /*****************************************/
  898.  
  899.   'ERASE 'REDIRECT_FILE' 1>NUL 2>NUL'       /* Clear redirection file first */
  900.   call lineout REDIRECT_FILE, lf_name
  901.   call lineout REDIRECT_FILE, LOG_PATH||LOG_FILE
  902.   call stream REDIRECT_FILE, c, 'close'
  903.  
  904. /*******************************************/
  905. /* Get drive name from the pmtindex file                */
  906. /******************************************/
  907.  
  908. /* rexx code to read an index file and get direcroy info */
  909.  
  910. findpath = lf_name               /* string being searched for in pmtindex.dat */
  911. indxfile = DBM_DIR"\PMTINDEX.DAT"
  912. if (LINES(indxfile) =0) then do
  913.  say "no index file exists"
  914.  say "return to caller with error"
  915.  exit
  916. end
  917. not_found = 1
  918. DO WHILE ((LINES(indxfile) =1) & (not_found))
  919.  istring=LINEIN(indxfile)    /* last line */
  920.  blank_loc =POS(' ',istring)
  921.  temppath = LEFT(istring,blank_loc-1)
  922. if (temppath=findpath) then not_found =0
  923. end
  924.  
  925. call LINEOUT indxfile
  926.                                            /* Get the Backup set name where  */
  927.                                          /* the database is stored on PMTAPE */
  928. tape_directory = SUBSTR(istring,blank_loc+1)
  929. dot_loc =POS('.',temppath)
  930. t2file = LEFT(temppath,dot_loc-10)
  931. call verify_path(t2file)                   /* Make sure the directory exists */
  932.  
  933.  
  934. /*****************************************/
  935. /* Build the .tpf file and  Call PMTAPE to get the file from tape            */
  936. /*****************************************/
  937.  
  938. slash_loc =POS('\',lf_name)
  939. lf2_name = SUBSTR(lf_name,slash_loc+1)
  940. call rmvdirs
  941. tpffile=PMT_DIR'\pmtape\database.tpf'
  942. tpffile2=PMT_DIR'\pmtape\retrv.tpf'
  943. 'ERASE 'tpffile' 1>NUL 2>NUL'
  944. 'ERASE 'tpffile2' 1>NUL 2>NUL'
  945. call LINEOUT tpffile,"!Restore",1
  946. call LINEOUT tpffile,"/w socnf /l "PMT_DIR"\PMTAPE\RESTORE.LOG i /m /t "LOG_PATH"  /p 2 /k 0 /o 2"
  947. call LINEOUT tpffile,"/b /b rhs "
  948. call LINEOUT tpffile,"/s "'"'tape_directory"\"lf2_name""""
  949. call LINEOUT tpffile2,"!Restore",1
  950. call LINEOUT tpffile2,"/w socnf /l "PMT_DIR"\PMTAPE\RESTORE.LOG i /m /t "RTRV_DIR"  /p 2 /k 1 /o 2"
  951. call LINEOUT tpffile2,"/b /b rhs /q"
  952. call LINEOUT tpffile2,"/s "'"'tape_directory"\*"""
  953. call LINEOUT tpffile
  954. call LINEOUT tpffile2
  955. 'PMTAPE 'PMT_DIR'\PMTAPE\DATABASE.TPF'
  956. 'PMTAPE 'PMT_DIR'\PMTAPE\RETRV.TPF'
  957. call checkrc
  958.  
  959.   if sqluexitrc <> IBM_RC.OK then
  960.     signal FINISH
  961.  
  962. return
  963. /************************* END TAPE_RETRIEVE PROCEDURE *********************/
  964.  
  965. /******************************* HALT PROCEDURE ****************************/
  966. /* Called when a CTRL-C is received                                         */
  967. /****************************************************************************/
  968. HALT:
  969.   ELINE =  "USER TERMINATION"
  970.   sqluexitrc=IBM_RC.OPCAN
  971.   signal FINISH
  972. /***************************** END HALT PROCEDURE **************************/
  973.  
  974.  
  975. /****************************** FINISH PROCEDURE ****************************/
  976. /* Check for interactive mode and select appropriate exit routine.          */
  977. /* If in interactive mode, it allows the User to determine what return code */
  978. /* to return back to the Database Manager.                                  */
  979. /****************************************************************************/
  980. FINISH:
  981.  
  982.   say DT                                                       /* Date/time */
  983.   say PARMS                                         /* Passed in parameters */
  984.   say ''
  985.   say ELINE                                                   /* Error text */
  986.   if sqluexitrc = 0 then
  987.     signal EXITOK
  988.     else do
  989.    pull hi
  990.    signal EXITERR
  991.    end
  992. /**************************** END FINISH PROCEDURE **************************/
  993.  
  994.  
  995. /****************************** EXITERR PROCEDURE **************************/
  996. /* Procedure handles error conditions for SQLUEXIT.It always logs the error */
  997. /* and configuration in an error file.                                      */
  998. /***************************************************************************/
  999. EXITERR:
  1000.  
  1001.   if VERIFY_DIR = 'TRUE' then
  1002.   do
  1003.     call lineout UEXIT_ERR, ' '
  1004.  
  1005.     /**  Timestamp this error in the error file  **/
  1006.     RT = '*****  SQLUEXIT ERROR ON 'ODATE' @ 'OTIME
  1007.     call lineout UEXIT_ERR, RT
  1008.  
  1009.     /**  Output the SQLUEXIT configuration to the error file  **/
  1010.     RT = '    SQLUEXIT CONFIGURATION: 'AUDIT
  1011.  
  1012.     call lineout UEXIT_ERR, RT
  1013.  
  1014.     /**  Output the parameters received to the error file  **/
  1015.     call lineout UEXIT_ERR, PARMS
  1016.  
  1017.     /**  Output the Error message to the error file **/
  1018.     call lineout UEXIT_ERR, ELINE
  1019.  
  1020.     /**  Output the error code being returned to the DBM in the error file **/
  1021.     RT = '    ERROR CODE RETURNED TO DBM: <'sqluexitrc'>'
  1022.     call lineout UEXIT_ERR, RT
  1023.  
  1024.     if AUDIT = 'Y' then                                  /* Auditing enabled? */
  1025.       do
  1026.         call lineout UEXIT_LOG, ELINE
  1027.         RT =  '    RETURNED DBM A VALUE OF <'sqluexitrc'>'
  1028.         call lineout UEXIT_LOG, RT
  1029.         call lineout UEXIT_LOG, ' '
  1030.       end
  1031.  
  1032.     say RT
  1033.   end
  1034.   else
  1035.     say '    Returned DBM a value of <'sqluexitrc'>'
  1036.   exit sqluexitrc
  1037. /**************************** END EXITERR PROCEDURE ************************/
  1038.  
  1039.  
  1040. /****************************** EXITOK PROCEDURE ***************************/
  1041. /* Routine handles normal exits from SQLUEXIT.                              */
  1042. /****************************************************************************/
  1043. EXITOK:
  1044.   RT = '    Returned DBM a value of <'sqluexitrc'>'
  1045.  
  1046.   if AUDIT = 'Y' then
  1047.     do
  1048.       call lineout UEXIT_LOG, RT
  1049.       call lineout UEXIT_LOG, ' '
  1050.     end
  1051.  
  1052.   say RT
  1053.  
  1054.   exit sqluexitrc
  1055. /**************************** END EXITOK PROCEDURE *************************/
  1056.