An old melody's lyrics say, "if it takes forever, I will wait for you." You may be willing to wait forever for another person, but having to do so for an AS/400 object is a bit too much. And that sort of thing is common enough in CL programming.
For example, suppose you have two batch jobs running in parallel. One of them calls a program that creates a summary file, which must be used by the other job. You don't want to schedule both jobs into a single-threaded job queue because there are portions of each job that can run at the same time without trouble, and you would save time by doing so.
Obviously, the second job must wait for the first one to create the file. You then have to code a loop in your CL program, checking for the existence of the summary file and, if it doesn't exist, delaying the job (DLYJOB command) for a short time before testing again.
Or consider having to wait for a data area to become available (it was allocated to another job). Again, you'd have to try to allocate it and, if it fails, delay the job and try again. It seems like this chore is common enough to deserve a simpler solution.
This problem can be solved with the Wait For Object command (WAITOBJ), which is shown in Figures 1a and 1b. When you include WAITOBJ in a CL program, the CL program will effectively wait until the condition you specify is satisfied, up to a maximum time that you also specify. If this maximum time is reached without satisfying the wait condition, WAITOBJ ends with an escape message CPF0002 which you can trap in your CL program with a MONMSG.
Parameter FOR determines what to wait for: the existence of an object (*EXIST), the nonexistence of an object (*NONEXIST), or the availability to allocate an object (*ALLOC).
Parameter OBJ and OBJTYPE define the object to wait for. Parameter MBR is required only if OBJTYPE(*FILE) is specified, and it refines the wait condition to a specific file member.
Parameter ALLOC is required only if FOR(*ALLOC) is specified. You use it to indicate what allocation you need to obtain for the object.
Parameter MAXNBRTRY indicates how many times the system will check for the object existence (or nonexistence, or availability to allocate it); you can enter a number between 1 and 86400, or *NOMAX. Parameter TRYWAIT indicates how many seconds to wait between attempts.
Suppose, that your CL program needs to wait for object MYLIB/MYFILE (type *FILE) to become available, since you have to allocate it exclusively. Code the following in your CL program:
WAITFILE FOR(*ALLOC) + OBJ(MYLIB/MYFILE) + OBJTYPE(*FILE) MBR(*FIRST) ALLOC(*EXCL) MAXNBRTRY(15) TRYWAIT(60)
Coded this way, the CL program will try a maximum of 15 times to allocate the file exclusively. Each time it fails, it will wait 60 seconds. If the allocation is unsuccessful after the total time (15 minutes), escape message CPF0002 will be returned to your CL program. Your CL program can then determine what to do in that case.
Besides entering the source and compiling, WAITOBJ requires the existence of a message file with at least two messages. The command definition's DEP statements make reference to messages OBJ0001 and OBJ0002. When the command is created, the MSGF parameter references message file WAITOBJ. If you already have a message file you can use it. You may have to change the message IDs to something else.
If you don't have a suitable message file, create it by executing the commands listed in 1c.
If you don't have a suitable message file, create it by executing the commands listed in Figure 1c.
TechTalk: Don't Get Stood Up
Figure 1A Command WAITOBJ
WAITOBJ: CMD PROMPT('Wait for Object') PARM KWD(FOR) TYPE(*CHAR) LEN(9) RSTD(*YES) + VALUES(*EXIST *NONEXIST *ALLOC) MIN(1) + PROMPT('Wait for') PARM KWD(OBJ) TYPE(Q1) MIN(1) PROMPT('Object name') PARM KWD(OBJTYPE) TYPE(*CHAR) LEN(8) RSTD(*YES) + VALUES(*ALRTBL *AUTL *CFGL *CHTFMT *CLD + *CLS *CMD *COSD *CSPMAP *CSPTBL *CTLD + *DEVD *DOC *DTAARA *DTADCT *DTAQ *EDTD + *FCT *FILE *FLR *FNTRSC *FORMDF *GSS + *JOBD *JOBQ *JRN *JRNRCV *LIB *LIND *MENU + *MODD *MSGF *MSGQ *OUTQ *OVL *PAGSEG *PDG + *PGM *PNLGRP *PRDAVL *PRDDFN *PRDLOD + *QMFORM *QMQRY *QRYDFN *RCT *SBSD *SCHIDX + *SPADCT *SSND *S36 *TBL *USRIDX *USRPRF + *USRQ *USRSPC) MIN(1) PROMPT('Object type') PARM KWD(MBR) TYPE(*NAME) LEN(10) SPCVAL((*NONE) + (*FIRST) (*LAST)) PROMPT('Member name, if + *FILE') PARM KWD(ALLOC) TYPE(*CHAR) LEN(7) RSTD(*YES) + VALUES(*SHRRD *SHRNUP *SHRUPD *EXCLRD + *EXCL) PROMPT('Desired lock state') PARM KWD(MAXNBRTRY) TYPE(*DEC) LEN(5 0) DFT(60) + RANGE(1 86400) SPCVAL((*NOMAX 99999)) + PROMPT('Maximum number of tries') PARM KWD(TRYWAIT) TYPE(*DEC) LEN(5 0) DFT(60) + RANGE(1 3600) PROMPT('Wait seconds + between tries') Q1: QUAL TYPE(*NAME) LEN(10) MIN(1) QUAL TYPE(*NAME) LEN(10) DFT(*LIBL) + SPCVAL((*LIBL) (*CURLIB)) PROMPT('Library') DEP CTL(&OBJTYPE *EQ *FILE) PARM((MBR)) + MSGID(OBJ0001) DEP CTL(&FOR *EQ *ALLOC) PARM((ALLOC)) + MSGID(OBJ0002)
TechTalk: Don't Get Stood Up
Figure 1B CL program OBJ008CL
OBJ008CL: + PGM PARM(&FOR &QUALOBJ &OBJTYPE &MBR &ALLOC &MAXNBRTRY &TRYWAIT) DCL VAR(&ALLOC) TYPE(*CHAR) LEN(7) DCL VAR(&FOR) TYPE(*CHAR) LEN(9) DCL VAR(&MAXNBRTRY) TYPE(*DEC) LEN(5 0) DCL VAR(&MAXTIME) TYPE(*DEC) LEN(10 0) DCL VAR(&MBR) TYPE(*CHAR) LEN(10) DCL VAR(&OBJ) TYPE(*CHAR) LEN(10) DCL VAR(&OBJLIB) TYPE(*CHAR) LEN(10) DCL VAR(&OBJTYPE) TYPE(*CHAR) LEN(8) DCL VAR(&QUALOBJ) TYPE(*CHAR) LEN(20) DCL VAR(&TIMEWAITED) TYPE(*DEC) LEN(10 0) DCL VAR(&TRYWAIT) TYPE(*DEC) LEN(5 0) IF COND(&MBR *EQ ' ' *AND &FOR *NE '*ALLOC') THEN(CHGVAR + VAR(&MBR) VALUE(*NONE)) /* Break qualified name */ CHGVAR VAR(&OBJ) VALUE(%SST(&QUALOBJ 1 10)) CHGVAR VAR(&OBJLIB) VALUE(%SST(&QUALOBJ 11 10)) /* Determine how much time to wait in total */ IF COND(&MAXNBRTRY *LT 99999) THEN(DO) CHGVAR VAR(&MAXTIME) VALUE(&TRYWAIT * &MAXNBRTRY) CHGVAR VAR(&TIMEWAITED) VALUE(0) ENDDO /* Loop until condition satisfied or time expires */ /* Check for object existence */ LOOP: + IF COND(&FOR *EQ '*EXIST') THEN(DO) CHKOBJ OBJ(&OBJLIB/&OBJ) OBJTYPE(&OBJTYPE) MBR(&MBR) MONMSG MSGID(CPF9801 CPF9810 CPF9815) EXEC(GOTO CMDLBL(WAIT)) GOTO CMDLBL(ENDPGM) ENDDO /* Check for object nonexistence */ IF COND(&FOR *EQ '*NONEXIST') THEN(DO) CHKOBJ OBJ(&OBJLIB/&OBJ) OBJTYPE(&OBJTYPE) MBR(&MBR) MONMSG MSGID(CPF9801 CPF9810 CPF9815) EXEC(GOTO CMDLBL(ENDPGM)) GOTO CMDLBL(WAIT) ENDDO /* Check for object allocation */ IF COND(&FOR *EQ '*ALLOC') THEN(DO) IF COND(&OBJTYPE *EQ '*FILE') THEN(DO) ALCOBJ OBJ((&OBJLIB/&OBJ &OBJTYPE &ALLOC &MBR)) WAIT(0) MONMSG MSGID(CPF1002 CPF1040 CPF1085) EXEC(GOTO CMDLBL(WAIT)) ENDDO ELSE CMD(DO) ALCOBJ OBJ((&OBJLIB/&OBJ &OBJTYPE &ALLOC)) WAIT(0) MONMSG MSGID(CPF1002 CPF1040 CPF1085) EXEC(GOTO CMDLBL(WAIT)) ENDDO GOTO CMDLBL(ENDPGM) ENDDO /* Wait before attempting again */ WAIT: + DLYJOB DLY(&TRYWAIT) IF COND(&MAXNBRTRY *LT 99999) THEN(DO) CHGVAR VAR(&TIMEWAITED) VALUE(&TIMEWAITED + &TRYWAIT) IF COND(&TIMEWAITED *GE &MAXTIME) THEN(DO) SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Maximum + time expired without satisfying wait condition') + MSGTYPE(*DIAG) SNDPGMMSG MSGID(CPF0002) MSGF(QCPFMSG) MSGTYPE(*ESCAPE) GOTO CMDLBL(ENDPGM) ENDDO ENDDO GOTO CMDLBL(LOOP) /* End program */ ENDPGM: + ENDPGM
TechTalk: Don't Get Stood Up
Figure 1C Creating the Message File
Figure 1c: Creating the Message File CRTMSGF MSGF(xxx/WAITOBJ) TEXT('Messages for WAITOBJ command') ADDMSGD MSGID(OBJ0001) MSGF(xxx/WAITOBJ) MSG('MEMBER parameter + must be entered if OBJTYPE(*FILE) is specified.') ADDMSGD MSGID(OBJ0002) MSGF(xxx/WAITOBJ) MSG('ALLOC parameter + must be entered if FOR(*ALLOC) is specified.')
LATEST COMMENTS
MC Press Online