We have a job that runs at 11:00 PM each night. This job mass-updates several database files, and it requires that no one be using options 1, 2, 13, or 14 of one of our menus: if our users stay on any of these options all night, the mass-update job will not run.
We needed a program that would give these users two minutes to return to the menu, or force them off the system. Because options 1, 2, 13, and 14 of the menu use database file TRANSWORK (and no other jobs use it), we took advantage of this situation and created program JBS001CL, which is shown in 2.
We needed a program that would give these users two minutes to return to the menu, or force them off the system. Because options 1, 2, 13, and 14 of the menu use database file TRANSWORK (and no other jobs use it), we took advantage of this situation and created program JBS001CL, which is shown in Figure 2.
First, the program waits until 11:00 PM by issuing a DLYJOB command. At that time it will send a break message to all the workstations that we consider likely to be using the menu options.
The ALCOBJ command tries to grab exclusive control over database file TRANSWORK, waiting a maximum of 120 seconds (2 minutes). If it cannot obtain an exclusive lock on the file, it branches to program tag OUTAHERE (very appropriately). However, if a lock is obtained it will be because no users are on the mentioned options of the menu; in this case, the program goes on and mass-updates the database files, deallocates the exclusive lock on TRANSWORK, and sends another break message to the same workstations, announcing that they may use their menus normally.
Label OUTAHERE runs a WRKOBJLCK to determine who is using the menu options -- remember that this means they are using file TRANSWORK. An OVRPRTF with HOLD(*YES) guarantees that the printed output from WRKOBJLCK will be held, so we can CPYSPLF into our file TERMINATE; each record of file TERMINATE will contain the fully-qualified name of each job that was using file TRANSWORK.
The loop that follows reads file TERMINATE until the end is reached. For each record read, the ENDJOB command is executed with OPTION(*IMMED), thus forcing users off the system. When all records have been processed, we clear file TERMINATE and delete the spooled output from WRKOBJLCK (which was still on hold), and delete all file overrides before ending.
- J. Bret Shortall
If you need to keep users off menu options or jobs that do not use a unique database file, you can always create a data area specifically for this purpose. Each time a user selects the menu option, do an ALCOBJ to the data area, specifying a *SHRRD lock. When the job ends, issue a DLCOBJ to the same data area. Your all-important nighttime job could then function almost as depicted here, only attempting to allocate the data area with an *EXCL lock -- which will fail if at least one user is running the "forbidden" menu options.
TechTalk: Preventing Job Abends on Unattended Sys
Figure 2 CL program JBS001CL
JBS001CL: + PGM DCLF FILE(TERMINATE) DCL VAR(&JOB) TYPE(*CHAR) LEN(9) DCL VAR(&DATA) TYPE(*CHAR) LEN(4) DCL VAR(&ASTR) TYPE(*CHAR) LEN(1) DCL VAR(&USER) TYPE(*CHAR) LEN(10) DCL VAR(&NUMBER) TYPE(*CHAR) LEN(6) DLYJOB RSMTIME(230000) SNDBRKMSG MSG('*** TO ALL BILLING MENU USERS *** If you are + using option 1, 2, 13, or 14, please return to your menu. + You will be notified when you can use that option again.') + TOMSGQ(EDTDSP02 EDTDSP03) CHECK: + ALCOBJ OBJ((TRANSWORK *FILE *EXCL)) WAIT(120) MONMSG MSGID(CPF1002 CPF3130) EXEC(GOTO CMDLBL(OUTAHERE)) CALL PGM(MASSUPDATE) DLCOBJ OBJ((TRANSWORK *FILE *EXCL)) SNDBRKMSG MSG('*** TO ALL BILLING MENU USERS *** You may now + use all options on your menu.') TOMSGQ(EDTDSP02 EDTDSP03) GOTO CMDLBL(END) OUTAHERE: + OVRPRTF FILE(QPDSPOLK) HOLD(*YES) WRKOBJLCK OBJ(TRANSWORK) OBJTYPE(*FILE) OUTPUT(*PRINT) CPYSPLF FILE(QPDSPOLK) TOFILE(TERMINATE) TAG: + RCVF MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(EOF)) CHGVAR VAR(&DATA) VALUE(%SST(&TERMINATE 1 10)) CHGVAR VAR(&JOB) VALUE(%SST(&TERMINATE 15 9)) CHGVAR VAR(&USER) VALUE(%SST(&TERMINATE 26 10)) CHGVAR VAR(&ASTR) VALUE(%SST(&TERMINATE 54 1)) CHGVAR VAR(&NUMBER) VALUE(%SST(&TERMINATE 37 6)) IF COND((&DATA *NE ' ') *AND (&ASTR *EQ '*')) THEN(DO) ENDJOB JOB(&NUMBER/&USER/&JOB) OPTION(*IMMED) ENDDO GOTO CMDLBL(TAG) EOF: + CLRPFM FILE(TERMINATE) DLTSPLF FILE(QPDSPOLK) DLTOVR FILE(*ALL) GOTO CMDLBL(CHECK) END: + ENDPGM