CL as a Never Ending Program
This is an example of a NEP written in CL.
NEP job stream CLP
There are time when it is desirable to create a Never Ending Program (NEP), a process that runs until instructed to quit. Here is an example that begins to monitor IFS folders for files to translate to DDB2 file data. The job delays at regular intervals until it receives instructions to stop.
Automated Data Mover
This program can function as a single pass, or as a NEP. If intended to run as a NEP the job will be submitted to a batch job queue. It may be run interactively, but it will make a single pass, and then exit. The multiple program calls use programs to retrieve control values from a database file to direct actions within the NEP. The program starts, checks the folder where data is expected (the import folder) and directs the data to the proper location. When it finishes the tasks, it checks to determine if it should exit, or wait until it is time to check for data again./*********************************************************************/ /* Program Name - ADM010CL */ /* */ /* Function - This program was designed as a NEP to monitor and */ /* process inbound order data. */ /* */ /* Programmer - Steve Croy xx/xx/xxxx */ /*********************************************************************/ /*********************************************************************/ /* Modification log */ /* */ /* Date Programmer Description */ /* xx/xx/xx xxxxxxxxxxxx xxxxxxxxxxxxxxx */ /*********************************************************************/ PGM PARM(&NEP) DCL VAR(&NEP) TYPE(*CHAR) LEN(1) DCL VAR(&IMPFOLDER) TYPE(*CHAR) LEN(128) DCL VAR(&ARCFOLDER) TYPE(*CHAR) LEN(128) DCL VAR(&LIBFILE) TYPE(*CHAR) LEN(128) DCL VAR(&LIB) TYPE(*CHAR) LEN(10) DCL VAR(&FILE) TYPE(*CHAR) LEN(10) DCL VAR(&exit) TYPE(*CHAR) LEN(4) DCL VAR(&SECONDS) TYPE(*DEC) LEN(3) DCL VAR(&SECONDA) TYPE(*CHAR) LEN(3) DCL VAR(&MSGKEY) TYPE(*CHAR) LEN(4) DCL VAR(&PGMNAME) TYPE(*CHAR) LEN(10) DCL VAR(&PROGRAM) TYPE(*CHAR) LEN(10) DCL VAR(&SENDER) TYPE(*CHAR) LEN(80) DCL VAR(&FILEPATH) TYPE(*CHAR) LEN(128) DCL VAR(&RETURN) TYPE(*CHAR) LEN(128) DCL VAR(&DB2FILE) TYPE(*CHAR) LEN(128) DCL VAR(&SYSLIB) TYPE(*CHAR) LEN(15) + VALUE('/QSYS.LIB/') DCL VAR(&QLIB) TYPE(*CHAR) LEN(5) + VALUE('.LIB/') DCL VAR(&QFIL) TYPE(*CHAR) LEN(6) + VALUE('.FILE/') DCL VAR(&QMBR) TYPE(*CHAR) LEN(5) + VALUE('.MBR/') DCL VAR(&JOBTYPE) TYPE(*CHAR) LEN(1) RTVJOBA TYPE(&JOBTYPE) IF COND(&JOBTYPE *EQ '1' *AND &NEP *EQ '1') + THEN(DO) SBMJOB CMD(CALL PGM(ADM010CL) PARM('1')) JOB(ADM010CL) GOTO TERMINATE ENDDO /*-------------------------------------------------------------------*/ /* Get the program name */ /*-------------------------------------------------------------------*/ SNDPGMMSG MSG(' ') TOPGMQ(*SAME) MSGTYPE(*INFO) + KEYVAR(&MSGKEY) RCVMSG PGMQ(*SAME) MSGTYPE(*INFO) RMV(*YES) + SENDER(&SENDER) CHGVAR VAR(&PGMNAME) VALUE(%SST(&SENDER 56 10)) INITIATE: IF COND(&NEP *EQ '0') THEN(GOTO CMDLBL(IMPORT)) /*-------------------------------------------------------------------*/ /* Check to see if the program should quit */ /*-------------------------------------------------------------------*/ CHECKEXIT: CALL PGM(ADM005RP) PARM(&PGMNAME 'EXIT' &RETURN) IF COND(&RETURN *EQ 'EXIT') THEN(GOTO + CMDLBL(TERMINATE)) /*-------------------------------------------------------------------*/ /* Get the folder where the IFS file is stored */ /*-------------------------------------------------------------------*/ IMPORT: CALL PGM(ADM005RP) PARM(&PGMNAME 'IMPORT' + &IMPFOLDER) /*-------------------------------------------------------------------*/ /* Get the folder where the IFS file is to be archived */ /*-------------------------------------------------------------------*/ ARCHIVE: CALL PGM(ADM005RP) PARM(&PGMNAME 'ARCHIVE' + &ARCFOLDER) /*-------------------------------------------------------------------*/ /* Get file name to use to convert the web data */ /*-------------------------------------------------------------------*/ DB2FILE: CALL PGM(ADM005RP) PARM(&PGMNAME 'DB2FILE' &LIBFILE) CHGVAR VAR(&LIB) VALUE(%SST(&LIBFILE 1 10)) CHGVAR VAR(&FILE) VALUE(%SST(&LIBFILE 11 10)) CHGVAR VAR(&DB2FILE) VALUE(&SYSLIB *TCAT &LIB *TCAT + &QLIB *TCAT &FILE *TCAT &QFIL *TCAT &FILE + *TCAT &QMBR) /*-------------------------------------------------------------------*/ /* Create a list of files in the folder */ /*-------------------------------------------------------------------*/ LIST: CALL PGM(ADM010RP) PARM(&IMPFOLDER) /*-------------------------------------------------------------------*/ /* Get the library and file as the target of the copy function. */ /*-------------------------------------------------------------------*/ READ: CALL PGM(ADM020RP) PARM(&FILEPATH) IF COND(&FILEPATH *NE '*****') THEN(DO) CPYFRMSTMF FROMSTMF(&FILEPATH) TOMBR(&DB2FILE) + MBROPT(*REPLACE) /*-------------------------------------------------------------------*/ /* Retrieve the translate program name. */ /*-------------------------------------------------------------------*/ XLATEPGM: CALL PGM(ADM005RP) PARM(&file 'XLATE' + &RETURN) CHGVAR VAR(&PROGRAM) VALUE(%SST(&RETURN 1 10)) CALL PGM(&PROGRAM) MOVE OBJ(&FILEPATH) TODIR(&ARCFOLDER) DTAFMT(*TEXT) GOTO CMDLBL(READ) ENDDO IF COND(&NEP *EQ '0') THEN(GOTO CMDLBL(TERMINATE)) GETDELAY: CALL PGM(ADM005RP) PARM(&PGMNAME 'DELAY' + &RETURN) CHGVAR VAR(&SECONDA) VALUE(%SST(&RETURN 1 3)) CHGVAR VAR(&SECONDS) VALUE(&SECONDA) DLYJOB DLY(&SECONDS) GOTO CMDLBL(INITIATE) TERMINATE: ENDPGM
Editor NEP
This program was designed to edit the inbound data. Like the data mover, it wakes at regular intervals to determine if there is any data to editor. It checks the incoming data for errors and completness. Errors will be flagged. If there are no errors it will forward the data to the translator. After checking for data to edit it tests whether a request to exit has been issued./*********************************************************************/ /* Program Name - ADM350CL */ /* */ /* Function - This program was designed call the order editor */ /* for the Automated Data Mover system */ /* */ /* Programmer - Steve Croy 99/99/9999 */ /*********************************************************************/ /*********************************************************************/ /* Modification log */ /* */ /* Date Programmer Description */ /*********************************************************************/ PGM PARM(&NEP) DCL VAR(&NEP) TYPE(*CHAR) LEN(1) DCL VAR(&JOBTYPE) TYPE(*CHAR) LEN(1) DCL VAR(&exit) TYPE(*CHAR) LEN(4) DCL VAR(&SECONDS) TYPE(*DEC) LEN(3) DCL VAR(&SECONDA) TYPE(*CHAR) LEN(3) DCL VAR(&MSGKEY) TYPE(*CHAR) LEN(4) DCL VAR(&PGMNAME) TYPE(*CHAR) LEN(10) DCL VAR(&PROGRAM) TYPE(*CHAR) LEN(10) DCL VAR(&SENDER) TYPE(*CHAR) LEN(80) DCL VAR(&RETURN) TYPE(*CHAR) LEN(128) RTVJOBA TYPE(&JOBTYPE) IF COND(&JOBTYPE *EQ '1') THEN(DO) SBMJOB CMD(CALL PGM(ADM350CL) PARM(&NEP)) + JOB(ADM350CL) GOTO TERMINATE ENDDO /*-------------------------------------------------------------------*/ /* Get the program name */ /*-------------------------------------------------------------------*/ SNDPGMMSG MSG(' ') TOPGMQ(*SAME) MSGTYPE(*INFO) + KEYVAR(&MSGKEY) RCVMSG PGMQ(*SAME) MSGTYPE(*INFO) RMV(*YES) + SENDER(&SENDER) CHGVAR VAR(&PGMNAME) VALUE(%SST(&SENDER 56 10)) INITIATE: /*-------------------------------------------------------------------*/ /* Check to see if the program should quit */ /*-------------------------------------------------------------------*/ CHECKEXIT: CALL PGM(ADM005RP) PARM(&PGMNAME 'EXIT' &RETURN) IF COND(&RETURN *EQ 'EXIT') THEN(GOTO + CMDLBL(TERMINATE)) /*-------------------------------------------------------------------*/ /* Check to see if any pending orders should be split */ /* Orders with both 01 and 05 frames will be split into separate */ /* orders. Orders with 02 and 04 frames will also be split. */ /*-------------------------------------------------------------------*/ SPLIT: CALL PGM(ADM005RP) PARM(&PGMNAME 'SPLIT' + &RETURN) IF COND(%SST(&RETURN 1 3) *EQ 'YES') THEN(CALL + PGM(ADM325RP)) ELSE CMD(CALL PGM(ADM326RP)) EDIT: CALL PGM(ADM350RP) IF COND(&NEP *EQ '0') THEN(GOTO CMDLBL(TERMINATE)) GETDELAY: CALL PGM(ADM005RP) PARM(&PGMNAME 'DELAY' + &RETURN) CHGVAR VAR(&SECONDA) VALUE(%SST(&RETURN 1 3)) CHGVAR VAR(&SECONDS) VALUE(&SECONDA) DLYJOB DLY(&SECONDS) GOTO CMDLBL(INITIATE) TERMINATE: ENDPGM
Tranlator NEP
This NEP program functions as a translation process. Inbound data is stored in a standard format. This process examines the data received and maps the data to the prodcution database format. Like the mover and the editor, it wakes periodically to determine if there is data needing translation. It performs the task, then tests to see if it should exit or continue working.
/*********************************************************************/ /* Program Name - ADM400CL */ /* */ /* Function - This program was designed call the order XLATE */ /* for the Automated Data Mover system */ /* */ /* Programmer - Steve Croy 99/99/9999 */ /*********************************************************************/ /*********************************************************************/ /* Modification log */ /* */ /* Date Programmer Description */ /* xx/xx/xx xxxxxxxxxxxx xxxxxxxxxxxxxxx */ /*********************************************************************/ PGM PARM(&NEP) DCL VAR(&NEP) TYPE(*CHAR) LEN(1) DCL VAR(&JOBTYPE) TYPE(*CHAR) LEN(1) DCL VAR(&exit) TYPE(*CHAR) LEN(4) DCL VAR(&SECONDS) TYPE(*DEC) LEN(3) DCL VAR(&SECONDA) TYPE(*CHAR) LEN(3) DCL VAR(&MSGKEY) TYPE(*CHAR) LEN(4) DCL VAR(&PGMNAME) TYPE(*CHAR) LEN(10) DCL VAR(&PROGRAM) TYPE(*CHAR) LEN(10) DCL VAR(&SENDER) TYPE(*CHAR) LEN(80) DCL VAR(&RETURN) TYPE(*CHAR) LEN(128) RTVJOBA TYPE(&JOBTYPE) IF COND(&JOBTYPE *EQ '1') THEN(DO) SBMJOB CMD(CALL PGM(ADM400CL) PARM(&NEP)) + JOB(ADM400CL) GOTO TERMINATE ENDDO /*-------------------------------------------------------------------*/ /* Get the program name */ /*-------------------------------------------------------------------*/ SNDPGMMSG MSG(' ') TOPGMQ(*SAME) MSGTYPE(*INFO) + KEYVAR(&MSGKEY) RCVMSG PGMQ(*SAME) MSGTYPE(*INFO) RMV(*YES) + SENDER(&SENDER) CHGVAR VAR(&PGMNAME) VALUE(%SST(&SENDER 56 10)) INITIATE: /*-------------------------------------------------------------------*/ /* Check to see if the program should quit */ /*-------------------------------------------------------------------*/ CHECKEXIT: CALL PGM(ADM005RP) PARM(&PGMNAME 'EXIT' &RETURN) IF COND(&RETURN *EQ 'EXIT') THEN(GOTO + CMDLBL(TERMINATE)) EDIT: CALL PGM(ADM400RP) IF COND(&NEP *EQ '0') THEN(GOTO CMDLBL(TERMINATE)) GETDELAY: CALL PGM(ADM005RP) PARM(&PGMNAME 'DELAY' + &RETURN) CHGVAR VAR(&SECONDA) VALUE(%SST(&RETURN 1 3)) CHGVAR VAR(&SECONDS) VALUE(&SECONDA) DLYJOB DLY(&SECONDS) GOTO CMDLBL(INITIATE) TERMINATE: ENDPGM