HOWTO:User Exits
User Exits
How to Check the Objects in a Transfer
Before or during the transfer you want to do some checking and based on the outcome you want to stop the transfer or remove the object.
Before a Transfer
If you want to check the objects before a transfer you have to use the Exception Mechanism and create an Exception program that does the checking. Then based on the result you can send an escape message that will cancel the transfer. You can also blank the target locations of the object so that it does not get included in the transfer.
Steps:
- Create and compile an Exception Program by copying QUSRSRC(OME__03C)
- Create an Exception that uses the program (STRXFM)
- Create an Exception Selection (STRXSM) that activates the selection on UEP-3 with When to Activate set to 4=Pre-Processing
During a Transfer
If you want to check the objects during a transfer you can use the Action mechanism. If the Action must be critical then place it in an Action Group first. Create an Exception procedure to do the checking. Then create an Action that invokes the Exception procedure by using the STRPRCOMS command. Then based on the result you can set the return status to *TERM to cancel the transfer and start rollback for any object already processed. You can also blank the target locations of the object so that it gets kicked from the transfer.
Further reading
- What are exception selections
- What are exception functions
- OMS Exception Management
- Execute an Exception Procedure
- Actions Users Guide
Example of an Exception Procedure
/* ---------------------------------------------------------------- */ /* Program prevents *QRYDFN obejcts to be processed */ /* they will be removed from the transfer */ /* This is an example exception procedure. */ /* ---------------------------------------------------------------- */ /* ------------------------------------------------------- */ /* Program start */ /* ------------------------------------------------------- */ PGM PARM(&XFUC &XUEP &CRII &FREE &BUF &STAT) /* ------------------------------------------------------- */ /* Declare parameters */ /* ------------------------------------------------------- */ DCL VAR(&XFUC) TYPE(*CHAR) LEN(10) DCL VAR(&XUEP) TYPE(*CHAR) LEN(1) DCL VAR(&CRII) TYPE(*CHAR) LEN(1) DCL VAR(&FREE) TYPE(*CHAR) LEN(256) DCL VAR(&BUF) TYPE(*CHAR) LEN(1024) DCL VAR(&STAT) TYPE(*CHAR) LEN(5) /* ------------------------------------------------------- */ /* Initialize the return status with *NORM */ /* ------------------------------------------------------- */ CHGVAR VAR(&STAT) VALUE('*NORM') /* ---------------------------------------------------------------- */ /* Processing starts here. */ /* This is an example exception procedure. */ /* ---------------------------------------------------------------- */ /* ------------------------------------------------------- */ /* Pull values from the buffer. */ /* ------------------------------------------------------- */ PULLVAROMS BUF(&BUF) INTL(*V5R1M0) APPL(&APPL) + OBJC(&OBJC) OBJT(&OBJT) FROL(&FROL) /* ------------------------------------------------------- */ /* Test the object code */ /* ------------------------------------------------------- */ IF COND(&OBJT *EQ '*QRYDFN') THEN(DO) /* This is how to remove this object from the transfer */ PUSHVAROMS TOOL() PUSHVAROMS TSRL() PUSHVAROMS TSRF() PUSHVAROMS TSRM() CHGVAR VAR(&STAT) VALUE('*TERM') ENDDO ENDPGM
How To remove an object from the transfer at runtime
You can remove a component from the transfer at runtime by blanking the target fields in an exception procedure:
Example of an Exception Procedure
/* ---------------------------------------------------------------- */ /* Program prevents *QRYDFN obejcts to be processed */ /* they will be removed from the transfer */ /* This is an example exception procedure. */ /* ---------------------------------------------------------------- */ /* ------------------------------------------------------- */ /* Program start */ /* ------------------------------------------------------- */ PGM PARM(&XFUC &XUEP &CRII &FREE &BUF &STAT) /* ------------------------------------------------------- */ /* Declare parameters */ /* ------------------------------------------------------- */ DCL VAR(&XFUC) TYPE(*CHAR) LEN(10) DCL VAR(&XUEP) TYPE(*CHAR) LEN(1) DCL VAR(&CRII) TYPE(*CHAR) LEN(1) DCL VAR(&FREE) TYPE(*CHAR) LEN(256) DCL VAR(&BUF) TYPE(*CHAR) LEN(1024) DCL VAR(&STAT) TYPE(*CHAR) LEN(5) /* ------------------------------------------------------- */ /* Initialize the return status with *NORM */ /* ------------------------------------------------------- */ CHGVAR VAR(&STAT) VALUE('*NORM') /* ---------------------------------------------------------------- */ /* Processing starts here. */ /* This is an example exception procedure. */ /* ---------------------------------------------------------------- */ /* ------------------------------------------------------- */ /* Pull values from the buffer. */ /* ------------------------------------------------------- */ PULLVAROMS BUF(&BUF) INTL(*V5R1M0) APPL(&APPL) + OBJC(&OBJC) OBJT(&OBJT) FROL(&FROL) /* ------------------------------------------------------- */ /* Test the object code */ /* ------------------------------------------------------- */ IF COND(&OBJT *EQ '*QRYDFN') THEN(DO) /* This is how to remove this object from the transfer */ PUSHVAROMS TOOL() PUSHVAROMS TSRL() PUSHVAROMS TSRF() PUSHVAROMS TSRM() CHGVAR VAR(&STAT) VALUE('*TERM') ENDDO ENDPGM
How To Change the Target Location of an Object at Runtime
You can change the target location at runtime by using an Action or Exception command CHGVAROMS. You can also create an Exception Procedure that will change the target variables in a program.
Change the Target Location at Runtime
/* ---------------------------------------------------------------- */ /* Program moves *QRYDFN objects to another library */ */ /* This is an example exception procedure. */ /* ---------------------------------------------------------------- */ /* ------------------------------------------------------- */ /* Program start */ /* ------------------------------------------------------- */ PGM PARM(&XFUC &XUEP &CRII &FREE &BUF &STAT) /* ------------------------------------------------------- */ /* Declare parameters */ /* ------------------------------------------------------- */ DCL VAR(&XFUC) TYPE(*CHAR) LEN(10) DCL VAR(&XUEP) TYPE(*CHAR) LEN(1) DCL VAR(&CRII) TYPE(*CHAR) LEN(1) DCL VAR(&FREE) TYPE(*CHAR) LEN(256) DCL VAR(&BUF) TYPE(*CHAR) LEN(1024) DCL VAR(&STAT) TYPE(*CHAR) LEN(5) /* ------------------------------------------------------- */ /* Initialize the return status with *NORM */ /* ------------------------------------------------------- */ CHGVAR VAR(&STAT) VALUE('*NORM') /* ---------------------------------------------------------------- */ /* Processing starts here. */ /* This is an example exception procedure. */ /* ---------------------------------------------------------------- */ /* ------------------------------------------------------- */ /* Pull values from the buffer. */ /* ------------------------------------------------------- */ PULLVAROMS BUF(&BUF) INTL(*V5R1M0) APPL(&APPL) + OBJC(&OBJC) OBJT(&OBJT) FROL(&FROL) /* ------------------------------------------------------- */ /* Test the object code */ /* ------------------------------------------------------- */ IF COND(&OBJT *EQ '*QRYDFN') THEN(DO) /* This is how to change the target library */ PUSHVAROMS TOOL('NEWLIB') ENDDO ENDPGM
How To Change source file record length for new objects
When a new object is created and the source file does not yet exist in the library the source file is created, the record length is determined as follows:
- First check the source file length in the dump library
- If it does not exist use 132 length
- if program omo008c2u exists then call it (see source file "QUSRSRC" in the TD/OMS library for an example)
- Does that program fail or does not exist then we create it with the found length
New object create source file
/* ---------------------------------------------------------------- */ /* Description */ /* ---------------------------------------------------------------- */ /* */ /* Program ....: OMO008C2U */ /* Function ...: Creates a source file in the "New Object" */ /* process */ /* Parameters .: &NSRF - New Source file */ /* &NSRL - New Source library */ /* &RECL - Proposed record lenght */ /* &STAT - Return status */ /* *NORM - Source was created normally */ /* *TERM - Sourcefile could not be created */ /* */ /* Compile this program if you want to override the source file */ /* creation in the 'new object' process of the GUI. */ /* */ /* ---------------------------------------------------------------- */ pgm parm(&NSRF &NSRL &RECL &STAT) DCL VAR(&NSRL) TYPE(*CHAR) LEN(10) DCL VAR(&NSRF) TYPE(*CHAR) LEN(10) DCL VAR(&recl) TYPE(*dec) LEN(15 6) DCL VAR(&STAT) TYPE(*CHAR) LEN(5) MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) chgvar &stat '*NORM' CRTSRCPF FILE(&NSRL/&NSRF) RCDLEN(&RECL) TEXT('Created by + TD/OMS') CCSID(*HEX) MONMSG MSGID(CPF5113 CPF7313) RETURN error: chgvar &stat '*TERM' monmsg (cpf0000 mch0000) dmpclpgm MONMSG MSGID(CPF0000) ENDPGM
Add Log entries to the TD/OMS Log
TD/OMS has a log that can be viewed with DSPLOGOMS (in the green screen) or through the various "transfer history" actions in the GUI. You can add your own log entries to the TD/OMS log file. The log file name is OMLOG. Adding entries can be done in two ways.
1. Log the last entries from the job log
Suppose you monitor a message and you want to log this message. The construct would be something like this:
CALL XYZ MONMSG CPF0000 exec(do) CALL OMX928C ENDDO
Calling OMX928C like this will log the last message in the program message queue and put it in the TD/OMS log file.
You may also log your own messages like this:
SNDPGMMSG MSGID(CPF9898) + MSGF(QCPFMSG) + MSGDTA('Hello World!') + TOPGMQ(*SAME) CALL OMX928C
PRE V13.0.1
If you are before TD/OMS version V13.0.1, the message will be added to the TD/OMS log file and removed from the joblog.
V13.0.1 and Higher
If you are on TD/OMS version V13.0.1 or higher, the message will NOT be removed from the joblog. In addition, when you log an ESCAPE message, also all diagnostic messages that precede the escape message will be copied into the TD/OMS log file.
2. Add your own trace and debug messages to the TD/OMS Log
Starting from version 11.1 you can put TD/OMS in debug mode using the STRSD command in the green screen. Service program OMLOGGER contains a number of procedures that enable you to add your debug and trace messages.
You can find examples on how to use the logging facility in member QUSRSRC/LOGTEST.CLLE.