Il valore di sistema QMAXJOB (intervallo valido: 32.000 – 970.000; valore predefinito = 163.520) definisce il numero massimo di lavori che possono esistere su un sistema IBM i. Questo valore tiene conto dei lavori attivi, dei lavori in coda e dei lavori che sono terminati ma che hanno file di spool collegati (*KEEP è il valore predefinito sia per il valore di sistema QSPLFACN che per l’attributo del lavoro SPLFACN).
Raggiungere questo limite rappresenta una condizione critica che può compromettere l’operatività del sistema rendendo impossibile avviare nuovi lavori, sino a renderlo inaccessibile se non tramite la console (il sistema riserva una voce della tabella dei lavori per la console per garantire l’accesso).
Il rischio maggiore è che, in assenza di un monitoraggio proattivo e di una gestione efficace dei lavori non più attivi, l’esaurimento del limite QMAXJOB si presenti improvvisamente, lasciando poche opzioni di intervento se non un IPL (Initial Program Load).
Quando il sistema si avvicina al numero massimo di lavori, il messaggio CPI1468, Tabella lavori di sistema quasi piena, viene inviato alla coda di messaggi QSYSOPR. Per impostazione predefinita, questo messaggio viene inviato per la prima volta quando le tabelle di lavoro del sistema raggiungono il 90% della loro capacità in base all’impostazione QMAXJOB. Il messaggio viene inviato nuovamente ogni volta che le tabelle di lavoro vengono estese per aggiungere altre strutture di lavoro.
È quindi fondamentale monitorare costantemente il numero di lavori attivi (visibile, ad esempio, tramite i comandi WRKSYSSTS e DSPSYSSTS o tramite la vista di sistema QSYS2.SYSTEM_STATUS_INFO_BASIC oppure controllabile con il servizio di sistema QSYS2.SYSLIMITS o monitorando la coda messaggi QSYSOPR) e adottare politiche di gestione automatica dei lavori terminati ma con file di spool collegati) oltre a valutare periodicamente l’adeguatezza del valore assegnato a QMAXJOB rispetto alla crescita e alla complessità del sistema IBM i.
Il programma RMVOLDSPLF, oggetto di questo articolo, può aiutare a limitare la crescita dei lavori nel sistema fornendo un aiuto nella gestione dei lavori terminati con file di spool collegati (che occupano entrate nella tabella dei lavori e partecipano ad incrementare il conteggio dei lavori presenti nel sistema) rimuovendo file di spool datati o privi di utilità per tentare di liberare entrate nella tabella dei lavori (visualizzabile con il comando DSPJOBTBL).
Nota. Per rimuovere dalla tabella lavori del sistema un lavoro terminato con file di spool collegati bisogna scollegare (CHGJOB JOB(…/…/…) .SPLFACN(*DETACH)) o cancellare (DLTSPLF FILE(…) JOB(…/…/…)) tutti i file di spool ad esso collegati.
Si tratta di un programma CLLE che fa uso della table function QSYS2.SPOOLED_FILE_INFO per selezionare i file di spool da rimuovere secondo i valori passati nel comando:
Remove old spooled files (SQL) (RMVOLDSPLF)
Immettere le scelte e premere Invio.
Job name . . . . . . . . . . . . Nome, *ALL
User name . . . . . . . . . . . Nome, *ALL, *CURRENT
File name . . . . . . . . . . . *ALL Nome, *ALL
User data . . . . . . . . . . . *ALL Valore carattere, *ALL
Output queue . . . . . . . . . . *ALL Nome, *ALL
Library . . . . . . . . . . . Nome, *CURLIB, *LIBL
Retention days . . . . . . . . . Numero
Codice sorgente comando:
RMVOLDSPLF: CMD PROMPT('Remove old spooled files (SQL)')
PARM KWD(JOBNAME) TYPE(*NAME) LEN(10) SPCVAL((*ALL)) +
MIN(1) ALWVAR(*YES) EXPR(*YES) PROMPT('Job name' 1)
PARM KWD(USERNAME) TYPE(*NAME) LEN(10) SPCVAL((*ALL) +
(*CURRENT)) MIN(1) ALWVAR(*YES) EXPR(*YES) +
PROMPT('User name' 2)
PARM KWD(DAYS) TYPE(*UINT2) MIN(1) ALWVAR(*YES) +
EXPR(*YES) PROMPT('Retention days' 6)
PARM KWD(FILENAME) TYPE(*NAME) LEN(10) DFT(*ALL) +
SPCVAL((*ALL)) ALWVAR(*YES) EXPR(*YES) +
PROMPT('File name' 3)
PARM KWD(USRDTA) TYPE(*CHAR) LEN(10) DFT(*ALL) +
SPCVAL((*ALL)) ALWVAR(*YES) EXPR(*YES) +
CASE(*MIXED) PROMPT('User data' 4)
PARM KWD(OUTQ) TYPE(QOUTQ) PROMPT('Output queue' 5)
QOUTQ: QUAL TYPE(*NAME) LEN(10) EXPR(*YES) DFT(*ALL) SPCVAL(*ALL)
QUAL TYPE(*NAME) LEN(10) SPCVAL((*CURLIB *CURLIB) +
(*LIBL *LIBL)) EXPR(*YES) PROMPT('Library')
PARM KWD(RMV) TYPE(*CHAR) LEN(4) RSTD(*YES) DFT(*YES) +
SPCVAL((*YES) (*NO)) EXPR(*YES) PMTCTL(*PMTRQS) +
PROMPT('Really remove?' 7)
PARM KWD(VERBOSE) TYPE(*CHAR) LEN(4) RSTD(*YES) +
DFT(*NO) SPCVAL((*YES) (*NO)) EXPR(*YES) +
PMTCTL(*PMTRQS) PROMPT('Verbose' 8)
Codice sorgente programma:
/* Before compiling: +
CREATE TABLE QTEMP.SQLOUT AS ( +
SELECT SFI.CREATION_TIMESTAMP CRTTIMSTM, SFI.SPOOLED_FILE_NAME SPLFNAME, +
SFI.SPOOLED_FILE_NUMBER SPLFNBR, SFI.QUALIFIED_JOB_NAME JOB +
FROM TABLE(QSYS2.SPOOLED_FILE_INFO()) SFI LIMIT 1 ) +
WITH NO DATA */
/* RMVOLDSPLF JOBNAME(QP0ZSPWP) USERNAME(*ALL) DAYS(60) +
[USRDTA(*ALL) OUTQ(*ALL)] */
PGM PARM(&PJOBNAM &PUSRNAM &PDAYS &PFILNAM &PUSRDTA +
&PQOUTQ &PRMV &PVERBOSE)
/* PARM: Start ****************************************************************/
DCL VAR(&PJOBNAM) TYPE(*CHAR) LEN(10)
DCL VAR(&PUSRNAM) TYPE(*CHAR) LEN(10)
DCL VAR(&PDAYS) TYPE(*UINT) LEN(2)
DCL VAR(&PFILNAM) TYPE(*CHAR) LEN(10)
DCL VAR(&PUSRDTA) TYPE(*CHAR) LEN(10)
DCL VAR(&PQOUTQ) TYPE(*CHAR) LEN(20)
DCL VAR(&OUTQNAM) TYPE(*CHAR) STG(*DEFINED) LEN(10) +
DEFVAR(&PQOUTQ 1)
DCL VAR(&OUTQLIB) TYPE(*CHAR) STG(*DEFINED) LEN(10) +
DEFVAR(&PQOUTQ 11)
DCL VAR(&PRMV) TYPE(*CHAR) LEN(4)
DCL VAR(&PVERBOSE) TYPE(*CHAR) LEN(4)
/* PARM: End ******************************************************************/
/* SUBR(RTVENDDAT): Start *****************************************************/
DCL VAR(&RTVENDDAT) TYPE(*INT) LEN(4)
DCL VAR(&CURDATE) TYPE(*CHAR) LEN(20)
DCL VAR(&CURYYMD) TYPE(*CHAR) STG(*DEFINED) LEN(8) +
DEFVAR(&CURDATE 1)
DCL VAR(&CURHHMISS) TYPE(*CHAR) STG(*DEFINED) LEN(6) +
DEFVAR(&CURDATE 9)
DCL VAR(&CURHH) TYPE(*CHAR) STG(*DEFINED) LEN(2) +
DEFVAR(&CURHHMISS 1)
DCL VAR(&CURMI) TYPE(*CHAR) STG(*DEFINED) LEN(2) +
DEFVAR(&CURHHMISS 3)
DCL VAR(&CURSS) TYPE(*CHAR) STG(*DEFINED) LEN(2) +
DEFVAR(&CURHHMISS 5)
DCL VAR(&CURMICSEC) TYPE(*CHAR) STG(*DEFINED) LEN(6) +
DEFVAR(&CURDATE 15)
DCL VAR(&LILDATE) TYPE(*INT)
DCL VAR(&YYYY_MM_DD) TYPE(*CHAR) LEN(10)
DCL VAR(&HH_MI_SS) TYPE(*CHAR) LEN(8)
DCL VAR(&CURTIMSTMP) TYPE(*CHAR) LEN(26)
DCL VAR(&TIMSEP) TYPE(*CHAR) LEN(1) VALUE(':')
/* SUBR(RTVENDDAT): End *******************************************************/
/* SUBR(RUNSQLSEL): Start *****************************************************/
DCL VAR(&RUNSQLSEL) TYPE(*INT) LEN(4)
/* RUNSQL */
DCL VAR(&SQL) TYPE(*CHAR) LEN(5000)
DCL VAR(&OUTQ) TYPE(*CHAR) LEN(21)
DCL VAR(&SQLLIB) TYPE(*CHAR) LEN(10) VALUE('QTEMP')
DCL VAR(&SQLFIL) TYPE(*CHAR) LEN(10) VALUE('SQLOUT')
DCL VAR(&SQLMBR) TYPE(*CHAR) LEN(10) VALUE('SQLOUT')
/* SUBR(RUNSQLSEL): End *******************************************************/
/* SUBR(RMVSPLFIL): Start *****************************************************/
DCL VAR(&RMVSPLFIL) TYPE(*INT) LEN(4)
DCLF FILE(SQLOUT) OPNID(SQLOUT) ALWVARLEN(*YES)
DCL VAR(&SQLROWS) TYPE(*DEC) LEN(10 0)
DCL VAR(&RCVSQLOUT) TYPE(*LGL) VALUE('1')
DCL VAR(&RCDNUM) TYPE(*UINT) LEN(4)
DCL VAR(&CMD_OK) TYPE(*UINT) LEN(4)
DCL VAR(&CMD_KO) TYPE(*UINT) LEN(4)
/* SUBR(RMVSPLFIL): End *******************************************************/
/* stat64 */
DCL VAR(&STATRTNVAL) TYPE(*INT) LEN(4)
DCL VAR(&STATPATH) TYPE(*CHAR) LEN(256)
DCL VAR(&STATBUFFER) TYPE(*CHAR) LEN(4096)
DCL VAR(&STATOBJTYP) TYPE(*CHAR) STG(*DEFINED) LEN(10) +
DEFVAR(&STATBUFFER 61)
/* DCL VAR(&NULL) TYPE(*CHAR) LEN(1) VALUE(X'00') */
/* strlen */
DCL VAR(&STRTMP) TYPE(*CHAR) LEN(32767)
DCL VAR(&LENINT) TYPE(*UINT) LEN(4)
/* DCL VAR(&NULL) TYPE(*CHAR) LEN(1) VALUE(X'00') */
/* QCMDEXC */
DCL VAR(&CMD) TYPE(*CHAR) LEN(5000)
DCL VAR(&CMDLEN) TYPE(*DEC) LEN(15 5) VALUE(5000)
/* RUNSQL */
/* DCL VAR(&SQL) TYPE(*CHAR) LEN(5000) */
/* API Error */
DCL VAR(&APIERROR) TYPE(*CHAR) LEN(1040)
DCL VAR(&AEBYTPRO) TYPE(*INT) STG(*DEFINED) LEN(4) +
DEFVAR(&APIERROR 1)
DCL VAR(&AEBYTAVL) TYPE(*INT) STG(*DEFINED) LEN(4) +
DEFVAR(&APIERROR 5)
DCL VAR(&AEEXCPID) TYPE(*CHAR) STG(*DEFINED) LEN(7) +
DEFVAR(&APIERROR 9)
DCL VAR(&AEEXCPDTA) TYPE(*CHAR) STG(*DEFINED) +
LEN(1024) DEFVAR(&APIERROR 17)
/* _MATPGMNM */
DCL VAR(&DATA) TYPE(*CHAR) LEN(80)
DCL VAR(&PGMNAME) TYPE(*CHAR) LEN(10)
DCL VAR(&PGMLIB) TYPE(*CHAR) LEN(10)
/* RTVNETA */
DCL VAR(&SYSNAME) TYPE(*CHAR) LEN(8)
DCL VAR(&CUST3) TYPE(*CHAR) STG(*DEFINED) LEN(3) +
DEFVAR(&SYSNAME 4)
/* RTVJOBA */
DCL VAR(&JOBNAME) TYPE(*CHAR) LEN(10)
DCL VAR(&JOBUSER) TYPE(*CHAR) LEN(10)
DCL VAR(&JOBNBR) TYPE(*CHAR) LEN(6)
DCL VAR(&LOGCLPGM) TYPE(*CHAR) LEN(10) VALUE(' ')
/* RCVMSG & SNDPGMMSG */
DCL VAR(&PRCNAME) TYPE(*CHAR) LEN(256) /* CALLPRC */
DCL VAR(&CMDNAME) TYPE(*CHAR) LEN(10)
DCL VAR(&ERROR) TYPE(*LGL) VALUE('0')
DCL VAR(&PGMERROR) TYPE(*CHAR) VALUE('-')
DCL VAR(&DUMP) TYPE(*LGL) VALUE('0')
DCL VAR(&SUBRNAME) TYPE(*CHAR) LEN(10)
DCL VAR(&ERR_PGM) TYPE(*CHAR) LEN(10)
DCL VAR(&ERR_FUN) TYPE(*CHAR) LEN(10)
DCL VAR(&ERR_TEXT) TYPE(*CHAR) LEN(100) /* For handled +
errors only */
DCL VAR(&MSGID) TYPE(*CHAR) LEN(7)
DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(512)
DCL VAR(&MSGDTALEN) TYPE(*DEC) LEN(5 0)
DCL VAR(&MSG) TYPE(*CHAR) LEN(1024)
DCL VAR(&MSGLEN) TYPE(*DEC) LEN(5 0)
DCL VAR(&SECLVL) TYPE(*CHAR) LEN(1024)
DCL VAR(&SECLVLLEN) TYPE(*DEC) LEN(5 0)
DCL VAR(&MSGF) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10)
DCL VAR(&MSGKEY) TYPE(*CHAR) LEN(4)
DCL VAR(&MSGKEYRQS) TYPE(*CHAR) LEN(4)
DCL VAR(&MSGTYPE) TYPE(*CHAR) LEN(7)
DCL VAR(&RTNTYPE) TYPE(*CHAR) LEN(2)
DCL VAR(&SENDER) TYPE(*CHAR) LEN(80)
DCL VAR(&SD_PGMSDR) TYPE(*CHAR) STG(*DEFINED) LEN(10) +
DEFVAR(&SENDER 27)
/* DCL VAR(&TOMSGQ) TYPE(*CHAR) LEN(10) */
/* DCL VAR(&TOMSGQLIB) TYPE(*CHAR) LEN(10) */
/* Constants */
DCL VAR(&NULL) TYPE(*CHAR) LEN(1) VALUE(X'00')
DCL VAR("E) TYPE(*CHAR) LEN(1) VALUE(X'7D')
/* Global monitor for error messages not handled */
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
/* Retrieving program name & library */
CHGVAR VAR(%BIN(&DATA 1 4)) VALUE(80)
CHGVAR VAR(%BIN(&DATA 5 4)) VALUE(80)
CHGVAR VAR(%BIN(&DATA 9 4)) VALUE(0)
CHGVAR VAR(%BIN(&DATA 13 4)) VALUE(0)
CALLPRC PRC('_MATPGMNM') PARM((&DATA))
CHGVAR VAR(&PGMNAME) VALUE(%SST(&DATA 51 10))
CHGVAR VAR(&PGMLIB) VALUE(%SST(&DATA 19 10))
/* Retrieving job attributes */
RTVJOBA JOB(&JOBNAME) USER(&JOBUSER) NBR(&JOBNBR) +
LOGCLPGM(&LOGCLPGM)
/* Checking parameters */
IF COND(&OUTQNAM *NE '*ALL') THEN(DO)
IF COND(&OUTQLIB *EQ ' ') THEN(DO)
CHGVAR VAR(&MSGDTA) VALUE('No library name +
specified for output queue.')
CHGVAR VAR(&PGMERROR) VALUE('1') /* *ESCAPE */
GOTO CMDLBL(DIAG)
ENDDO /* COND(&OUTQLIB *EQ ' ') */
ELSE CMD(DO)
CHKOBJ OBJ(&OUTQLIB/&OUTQNAM) OBJTYPE(*OUTQ)
ENDDO /* COND(&OUTQLIB *NE ' ') */
ENDDO /* COND(&OUTQNAM *NE '*ALL') */
/*** Start of program ***/
/* Retrieving ending date */
RTVSYSVAL SYSVAL(QDATETIME) RTNVAR(&CURDATE)
CALLSUBR SUBR(RTVENDDAT) RTNVAL(&RTVENDDAT)
SELECT
WHEN COND(&RTVENDDAT *EQ -1) THEN(DO) /* SUBR error */
CHGVAR VAR(&PGMERROR) VALUE('1') /* *ESCAPE */
GOTO CMDLBL(DIAG)
ENDDO /* COND(&RTVENDDAT *EQ -1) */
WHEN COND(&RTVENDDAT *EQ 0) THEN(DO) /* Ok */
ENDDO /* COND(&RTVENDDAT *EQ 0) */
OTHERWISE CMD(DO)
CHGVAR VAR(&MSGDTA) VALUE('Invalid return code from +
subroutine' *BCAT &SUBRNAME *TCAT '.')
CHGVAR VAR(&PGMERROR) VALUE('1') /* *ESCAPE */
CHGVAR VAR(&DUMP) VALUE('1') /* Dump enabled */
GOTO CMDLBL(DIAG)
ENDDO /* OTHERWISE */
ENDSELECT
/* Retrieving spooled files */
IF COND(&PQOUTQ *EQ '*ALL') THEN(DO)
CHGVAR VAR(&OUTQ) VALUE(&PQOUTQ)
ENDDO /* COND(&PQOUTQ *EQ '*ALL') */
ELSE CMD(DO)
CHGVAR VAR(&OUTQ) VALUE(&OUTQLIB *TCAT '/' *CAT &OUTQNAM)
ENDDO /* COND(&PQOUTQ *NE '*ALL') */
CHGVAR VAR(&SQL) VALUE('SELECT SFI.CREATION_TIMESTAMP, +
SFI.SPOOLED_FILE_NAME, SFI.SPOOLED_FILE_NUMBER, +
SFI.QUALIFIED_JOB_NAME FROM +
TABLE(QSYS2.SPOOLED_FILE_INFO(USER_NAME => ''' +
*CAT &PUSRNAM *TCAT ''', STATUS => ''*HELD +
*READY *SAVED'', OUTPUT_QUEUE => ''' *CAT &OUTQ +
*TCAT ''', USER_DATA => ''' *CAT &PUSRDTA *TCAT +
''', ENDING_TIMESTAMP => ''' *CAT &CURTIMSTMP +
*TCAT ''')) SFI')
IF COND((&PJOBNAM *NE '*ALL') *OR (&PFILNAM *NE +
'*ALL')) THEN(DO)
CHGVAR VAR(&SQL) VALUE(&SQL *BCAT 'WHERE')
ENDDO /* COND((&PJOBNAM *NE '*ALL') *OR (&PFILNAM *NE +
'*ALL')) */
IF COND(&PJOBNAM *NE '*ALL') THEN(DO)
CHGVAR VAR(&SQL) VALUE(&SQL *BCAT 'SFI.JOB_NAME = ''' +
*CAT &PJOBNAM *TCAT '''')
ENDDO /* COND(&PJOBNAM *NE '*ALL') */
IF COND((&PJOBNAM *NE '*ALL') *AND (&PFILNAM *NE +
'*ALL')) THEN(DO)
CHGVAR VAR(&SQL) VALUE(&SQL *BCAT 'AND')
ENDDO /* COND((&PJOBNAM *NE '*ALL') *AND (&PFILNAM *NE +
'*ALL')) */
IF COND(&PFILNAM *NE '*ALL') THEN(DO)
CHGVAR VAR(&SQL) VALUE(&SQL *BCAT +
'SFI.SPOOLED_FILE_NAME = ''' *CAT &PFILNAM +
*TCAT '''')
ENDDO /* COND(&PFILNAM *NE '*ALL') */
CHGVAR VAR(&SQL) VALUE(&SQL *BCAT 'ORDER BY +
SFI.CREATION_TIMESTAMP')
CHGVAR VAR(&MSGDTA) VALUE('Searching for spooled files to +
remove...')
CALLSUBR SUBR(RUNSQLSEL) RTNVAL(&RUNSQLSEL)
/* Removing spooled files */
SELECT
WHEN COND(&RUNSQLSEL *EQ -1) THEN(DO) /* SUBR error */
CHGVAR VAR(&PGMERROR) VALUE('1') /* *ESCAPE */
GOTO CMDLBL(DIAG)
ENDDO /* COND(&RUNSQLSEL *EQ -1) */
WHEN COND(&RUNSQLSEL *EQ 0) THEN(DO) /* Ok */
ENDDO /* COND(&RUNSQLSEL *EQ 0) */
OTHERWISE CMD(DO)
CHGVAR VAR(&MSGDTA) VALUE('Invalid return code from +
subroutine' *BCAT &SUBRNAME *TCAT '.')
CHGVAR VAR(&PGMERROR) VALUE('1') /* *ESCAPE */
CHGVAR VAR(&DUMP) VALUE('1') /* Dump enabled */
GOTO CMDLBL(DIAG)
ENDDO /* OTHERWISE */
ENDSELECT
CALLSUBR SUBR(RMVSPLFIL) RTNVAL(&RMVSPLFIL)
SELECT
WHEN COND(&RMVSPLFIL *EQ -1) THEN(DO) /* SUBR error */
CHGVAR VAR(&PGMERROR) VALUE('1') /* *ESCAPE */
GOTO CMDLBL(DIAG)
ENDDO /* COND(&RMVSPLFIL *EQ -1) */
WHEN COND(&RMVSPLFIL *EQ 0) THEN(DO) /* Ok */
ENDDO /* COND(&RMVSPLFIL *EQ 0) */
OTHERWISE CMD(DO)
CHGVAR VAR(&MSGDTA) VALUE('Invalid return code from +
subroutine' *BCAT &SUBRNAME *TCAT '.')
CHGVAR VAR(&PGMERROR) VALUE('1') /* *ESCAPE */
CHGVAR VAR(&DUMP) VALUE('1') /* Dump enabled */
GOTO CMDLBL(DIAG)
ENDDO /* OTHERWISE */
ENDSELECT
/*** End of program ***/
/* Cleaning up */
CALLSUBR SUBR(CLEANUP)
/* Exit */
GOTO CMDLBL(RETURN)
DIAG:
/* SUBRs don't have to send diagnostic messages, everything has to be done in +
MAIN */
/* Send diagnostic messagge for handled errors */
IF COND(&ERR_TEXT *NE ' ') THEN(DO)
SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&ERR_TEXT) +
TOPGMQ(*PRV (*)) TOMSGQ(*TOPGMQ) MSGTYPE(*DIAG)
ENDDO /* COND(&ERR_TEXT *NE ' ') */
IF COND(&MSGID *EQ ' ') THEN(DO)
CHGVAR VAR(&MSGID) VALUE('CPF9897')
ENDDO /* COND(&MSGID *EQ ' ') */
SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) +
TOPGMQ(*SAME (*)) TOMSGQ(*TOPGMQ) MSGTYPE(*DIAG)
IF COND(&PGMERROR *EQ '-') THEN(DO)
CHGVAR VAR(&PGMERROR) VALUE('0') /* *DIAG */
ENDDO /* COND(&PGMERROR *EQ '-') */
ERROR:
IF COND(&ERROR *EQ '1') THEN(RETURN)
CHGVAR VAR(&ERROR) VALUE('1')
RCVMSG PGMQ(*SAME) MSGTYPE(*LAST) RMV(*YES) MSG(&MSG) +
MSGLEN(&MSGLEN) SECLVL(&SECLVL) +
SECLVLLEN(&SECLVLLEN) MSGDTA(&MSGDTA) +
MSGDTALEN(&MSGDTALEN) MSGID(&MSGID) +
RTNTYPE(&RTNTYPE) MSGF(&MSGF) SNDMSGFLIB(&MSGFLIB)
/* MONMSG MSGID(CPF0000) */
IF COND((&PGMERROR *EQ '-') *OR (&DUMP)) THEN(DO) /* +
Global MONMSG or forced dump */
CHGVAR VAR(&ERR_TEXT) VALUE(' ') /* Handled errors only */
OVRPRTF FILE(QPPGMDMP) USRDTA(&PGMNAME) SPLFOWN(*JOB) +
OVRSCOPE(*CALLLVL)
MONMSG MSGID(CPF0000)
DMPCLPGM
MONMSG MSGID(CPF0000)
DLTOVR FILE(QPPGMDMP) LVL(*)
MONMSG MSGID(CPF0000)
ENDDO /* COND((&PGMERROR *EQ '-') *OR (&DUMP)) */
CALLSUBR SUBR(CLEANUP)
/* 02: Diagnostic - 15: Escape (exception already handled at time of RCVMSG) +
- 17: Escape (exception not handled at time of RCVMSG) */
IF COND((&RTNTYPE *EQ '02') *OR (&RTNTYPE *EQ '15') +
*OR (&RTNTYPE *EQ '17')) THEN(DO)
IF COND(&PGMERROR *EQ '0') THEN(DO)
/* Set DIAGNOSTIC message */
CHGVAR VAR(&MSGTYPE) VALUE('*DIAG')
ENDDO /* COND(&PGMERROR *EQ '0') */
ELSE CMD(DO)
/* Set ESCAPE message */
CHGVAR VAR(&MSGTYPE) VALUE('*ESCAPE')
ENDDO /* COND(&PGMERROR *NE '0') */
/* Send error message */
SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) +
MSGDTA(&MSGDTA) TOPGMQ(*PRV (*)) +
TOMSGQ(*TOPGMQ) MSGTYPE(&MSGTYPE)
MONMSG MSGID(CPF0000)
ENDDO /* COND((&RTNTYPE *EQ '02') *OR (&RTNTYPE *EQ +
'15') *OR (&RTNTYPE *EQ '17')) */
/* Normal exit */
RETURN:
RETURN
/* SUBR(RTVENDDAT): Start *****************************************************/
RTVENDDAT: SUBR SUBR(RTVENDDAT)
CHGVAR VAR(&SUBRNAME) VALUE('RTVENDDTA')
CHGVAR VAR(&RTVENDDAT) VALUE(0)
CALLPRC PRC(CEEDAYS) PARM((&CURYYMD) ('YYYYMMDD') +
(&LILDATE) (*OMIT))
MONMSG MSGID(CEE0000) EXEC(DO)
CHGVAR VAR(&ERR_PGM) VALUE('CEEDAYS')
CHGVAR VAR(&ERR_FUN) VALUE('PRC')
CHGVAR VAR(&ERR_TEXT) VALUE(&ERR_FUN *TCAT '(' *CAT +
&ERR_PGM *TCAT ')@SUBR(' *CAT &SUBRNAME +
*TCAT '): An error occurred. Check the job +
log.')
RTNSUBR RTNVAL(-1)
ENDDO /* MSGID(CEE0000) */
CHGVAR VAR(&LILDATE) VALUE(&LILDATE - &PDAYS)
CALLPRC PRC(CEEDATE) PARM((&LILDATE) ('YYYY-MM-DD') +
(&YYYY_MM_DD) (*OMIT))
MONMSG MSGID(CEE0000) EXEC(DO)
CHGVAR VAR(&ERR_PGM) VALUE('CEEDATE')
CHGVAR VAR(&ERR_FUN) VALUE('PRC')
CHGVAR VAR(&ERR_TEXT) VALUE(&ERR_FUN *TCAT '(' *CAT +
&ERR_PGM *TCAT ')@SUBR(' *CAT &SUBRNAME +
*TCAT '): An error occurred. Check the job +
log.')
RTNSUBR RTNVAL(-1)
ENDDO /* MSGID(CEE0000) */
IF COND(&PDAYS *EQ 0) THEN(DO)
CHGVAR VAR(&HH_MI_SS) VALUE(&CURHH *CAT &TIMSEP +
*CAT &CURMI *CAT &TIMSEP *CAT &CURSS)
CHGVAR VAR(&CURTIMSTMP) VALUE(&YYYY_MM_DD *BCAT +
&HH_MI_SS *CAT '.' *CAT &CURMICSEC)
ENDDO
ELSE CMD(DO)
CHGVAR VAR(&CURTIMSTMP) VALUE(&YYYY_MM_DD)
ENDDO
/* CHGVAR VAR(&RTVENDDAT) VALUE(0) */
ENDSUBR RTNVAL(&RTVENDDAT)
/* SUBR(RTVENDDAT): End *******************************************************/
/* SUBR(RUNSQLSEL): Start *****************************************************/
RUNSQLSEL: SUBR SUBR(RUNSQLSEL)
CHGVAR VAR(&SUBRNAME) VALUE('RUNSQLSEL')
CHGVAR VAR(&RUNSQLSEL) VALUE(0)
DLTF FILE(&SQLLIB/&SQLFIL)
MONMSG MSGID(CPF2105) EXEC(DO)
RCVMSG MSGTYPE(*LAST) RMV(*YES)
ENDDO /* MSGID(CPF2105) */
IF COND(&MSGID *EQ ' ') THEN(DO)
CHGVAR VAR(&MSGID) VALUE('CPI8859')
ENDDO /* COND(&MSGID *EQ ' ') */
IF COND(&MSGDTA *EQ ' ') THEN(DO)
CHGVAR VAR(&MSGDTA) VALUE('Running SQL statement...')
ENDDO /* COND(&MSGDTA *EQ ' ') */
SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) +
TOPGMQ(*EXT) TOMSGQ(*TOPGMQ) MSGTYPE(*STATUS)
CHGVAR VAR(&SQL) VALUE('CREATE TABLE' *BCAT &SQLLIB +
*TCAT '/' *CAT &SQLFIL *BCAT 'AS (' *CAT &SQL +
*TCAT ') WITH DATA')
RUNSQL SQL(&SQL) COMMIT(*NONE) NAMING(*SYS)
MONMSG MSGID(SQL0000) EXEC(DO)
CHGVAR VAR(&ERR_PGM) VALUE('RUNSQL')
CHGVAR VAR(&ERR_FUN) VALUE('CMD')
CHGVAR VAR(&ERR_TEXT) VALUE(&ERR_FUN *TCAT '(' *CAT +
&ERR_PGM *TCAT ')@SUBR(' *CAT &SUBRNAME +
*TCAT '): An error occurred. Check the job +
log.')
CHGVAR VAR(&MSGID) VALUE('CPF9897')
CHGVAR VAR(&MSGDTA) VALUE('SQL statement: "' *CAT +
&SQL *TCAT '".')
SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) +
TOPGMQ(*EXT) TOMSGQ(*TOPGMQ) MSGTYPE(*STATUS)
RTNSUBR RTNVAL(-1)
ENDDO /* MSGID(CPF0000) */
/* CHGVAR VAR(&RUNSQLSEL) VALUE(0) */
ENDSUBR RTNVAL(&RUNSQLSEL)
/* SUBR(RUNSQLSEL): End *******************************************************/
/* SUBR(RMVSPLFIL): Start *****************************************************/
RMVSPLFIL: SUBR SUBR(RMVSPLFIL)
CHGVAR VAR(&SUBRNAME) VALUE('RMVSPLFIL')
CHGVAR VAR(&RMVSPLFIL) VALUE(0)
RTVMBRD FILE(&SQLLIB/&SQLFIL) MBR(&SQLMBR) +
NBRCURRCD(&SQLROWS)
IF COND(&SQLROWS *GT 0) THEN(DO)
CHGVAR VAR(&MSGID) VALUE('CPI8859')
CHGVAR VAR(&MSGDTA) VALUE('Removing spooled files...')
SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) +
TOPGMQ(*EXT) TOMSGQ(*TOPGMQ) MSGTYPE(*STATUS)
CHGVAR VAR(&RCDNUM) VALUE(0)
CHGVAR VAR(&CMD_OK) VALUE(0)
CHGVAR VAR(&CMD_KO) VALUE(0)
OVRDBF FILE(SQLOUT) TOFILE(&SQLLIB/&SQLFIL) +
MBR(&SQLMBR) LVLCHK(*NO) OVRSCOPE(*CALLLVL)
CHGJOB LOGCLPGM(*NO)
MONMSG MSGID(CPF0000)
DOWHILE COND(&RCVSQLOUT)
RCVF OPNID(SQLOUT)
MONMSG MSGID(CPF0864) EXEC(LEAVE)
CHGVAR VAR(&RCDNUM) VALUE(&RCDNUM + 1)
CHGVAR VAR(&CMD) VALUE('DLTSPLF FILE(' *CAT +
%SST(&SQLOUT_SPLFNAME 3 10) *TCAT ') +
JOB(' *CAT %SST(&SQLOUT_JOB 3 28) *TCAT +
') SPLNBR(' *CAT %CHAR(&SQLOUT_SPLFNBR) +
*TCAT ')')
IF COND(&PVERBOSE *EQ '*YES') THEN(DO)
/* IF COND(&RCDNUM *LE 100) THEN(DO) */
SNDPGMMSG MSG('CMD: "' *CAT &CMD *TCAT '"')
/* ENDDO COND(&RCDNUM *LE 100) */
ENDDO /* COND(&PVERBOSE *EQ '*YES') */
IF COND(&PRMV *EQ '*YES') THEN(DO)
CALL PGM(QCMDEXC) PARM(&CMD &CMDLEN)
MONMSG MSGID(CPF0000) EXEC(DO)
CHGVAR VAR(&MSGID) VALUE('CPF9897')
CHGVAR VAR(&MSGDTA) VALUE('A problem +
occurred while deleting FILE(' +
*CAT %SST(&SQLOUT_SPLFNAME 3 10) +
*TCAT ') JOB(' *CAT +
%SST(&SQLOUT_JOB 3 28) *TCAT ') +
SPLNBR(' *CAT +
%CHAR(&SQLOUT_SPLFNBR) *TCAT ').')
CHGVAR VAR(&MSGTYPE) VALUE('*DIAG')
SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) +
MSGDTA(&MSGDTA) TOPGMQ(*PRV) +
TOMSGQ(*TOPGMQ) MSGTYPE(&MSGTYPE)
CHGVAR VAR(&CMD_KO) VALUE(&CMD_KO + 1)
ITERATE
ENDDO /* MSGID(CPF0000) */
ENDDO /* COND(&PRMV *EQ '*YES') */
CHGVAR VAR(&CMD_OK) VALUE(&CMD_OK + 1)
ENDDO /* DOWHILE */
CHGJOB LOGCLPGM(&LOGCLPGM)
MONMSG MSGID(CPF0000)
CLOSE OPNID(SQLOUT) /* RVCF */
DLTOVR FILE(SQLOUT) LVL(*) /* OVRDBF */
CHGVAR VAR(&MSGID) VALUE('CPI8859')
IF COND(&PRMV *EQ '*YES') THEN(DO)
CHGVAR VAR(&MSGDTA) VALUE('Spooled file +
selected:' *BCAT %CHAR(&SQLROWS) *BCAT +
'- Removed:' *BCAT %CHAR(&CMD_OK) *BCAT +
'- Failed:' *BCAT %CHAR(&CMD_KO))
ENDDO /* COND(&PRMV *EQ '*YES') */
ELSE CMD(DO)
CHGVAR VAR(&MSGDTA) VALUE('Spooled file +
selected:' *BCAT %CHAR(&SQLROWS))
ENDDO /* COND(&PRMV *NE '*YES') */
CHGVAR VAR(&MSGTYPE) VALUE('*COMP')
SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) +
TOPGMQ(*PRV) TOMSGQ(*TOPGMQ) MSGTYPE(&MSGTYPE)
ENDDO /* COND(&NBRCURRCD *GT 0) */
ELSE CMD(DO)
CHGVAR VAR(&MSGID) VALUE('CPI8859')
CHGVAR VAR(&MSGDTA) VALUE('No spooled files exist +
which match the selection criteria.')
CHGVAR VAR(&MSGTYPE) VALUE('*COMP')
SNDPGMMSG MSGID(&MSGID) MSGF(QCPFMSG) MSGDTA(&MSGDTA) +
TOPGMQ(*PRV) TOMSGQ(*TOPGMQ) MSGTYPE(&MSGTYPE)
ENDDO /* COND(&NBRCURRCD *EQ 0) */
/* CHGVAR VAR(&RMVSPLFIL) VALUE(0) */
ENDSUBR RTNVAL(&RMVSPLFIL)
/* SUBR(RMVSPLFIL): End *******************************************************/
/* SUBR(CLEANUP): Start *******************************************************/
CLEANUP: SUBR SUBR(CLEANUP)
CHGVAR VAR(&SUBRNAME) VALUE('CLEANUP')
DLTF FILE(&SQLLIB/&SQLFIL)
MONMSG MSGID(CPF2105) EXEC(DO)
RCVMSG MSGTYPE(*LAST) RMV(*YES)
ENDDO /* MSGID(CPF2105) */
MONMSG MSGID(CPF0000)
ENDSUBR RTNVAL(0)
/* SUBR(CLEANUP): End *********************************************************/
ENDPGM:
ENDPGM
Esempio di programma CLLE utilizzato per cancellare gli spooled file più vecchi di 7 giorni di alcune tipologie di lavori:
/* Before compiling: +
CREATE TABLE QTEMP.SQLOUT AS ( +
SELECT TOTAL_JOBS_IN_SYSTEM, MAXIMUM_JOBS_IN_SYSTEM +
FROM QSYS2.SYSTEM_STATUS_INFO_BASIC) +
WITH NO DATA */
PGM
DCLF FILE(SQLOUT) OPNID(SQLOUT) ALWVARLEN(*YES)
DCL VAR(&E) TYPE(*LGL) VALUE('0')
DCL VAR(&ERROR) TYPE(*LGL) VALUE('0')
/* RUNSQL */
DCL VAR(&SQL) TYPE(*CHAR) LEN(5000)
DCL VAR(&OUTQ) TYPE(*CHAR) LEN(21)
DCL VAR(&SQLLIB) TYPE(*CHAR) LEN(10) VALUE('QTEMP')
DCL VAR(&SQLFIL) TYPE(*CHAR) LEN(10) VALUE('SQLOUT')
DCL VAR(&SQLMBR) TYPE(*CHAR) LEN(10) VALUE('SQLOUT')
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
CALLSUBR SUBR(RTVTOTJOBS)
RMVOLDSPLF JOBNAME(QP0ZSPWT) USERNAME(*ALL) DAYS(7)
MONMSG MSGID(CPF0000) EXEC(CHGVAR VAR(&E) VALUE('1'))
RMVOLDSPLF JOBNAME(QP0ZSPWP) USERNAME(*ALL) DAYS(7)
MONMSG MSGID(CPF0000) EXEC(CHGVAR VAR(&E) VALUE('1'))
RMVOLDSPLF JOBNAME(QJVACMDSRV) USERNAME(*ALL) DAYS(7)
MONMSG MSGID(CPF0000) EXEC(CHGVAR VAR(&E) VALUE('1'))
RMVOLDSPLF JOBNAME(QZSHSH) USERNAME(*ALL) DAYS(7)
MONMSG MSGID(CPF0000) EXEC(CHGVAR VAR(&E) VALUE('1'))
RMVOLDSPLF JOBNAME(QRWTSRVR) USERNAME(QUSER) DAYS(7)
MONMSG MSGID(CPF0000) EXEC(CHGVAR VAR(&E) VALUE('1'))
RMVOLDSPLF JOBNAME(QPRTJOB) USERNAME(*ALL) USRDTA(QZRCSRVS) +
DAYS(7)
MONMSG MSGID(CPF0000) EXEC(CHGVAR VAR(&E) VALUE('1'))
CALLSUBR SUBR(RTVTOTJOBS)
GOTO CMDLBL(ENDCLP)
ERROR:
CHGVAR VAR(&ERROR) VALUE('1')
MONMSG MSGID(CPF0000)
GOTO CMDLBL(ENDCLP)
ENDCLP:
IF COND(&ERROR) THEN(DO)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) +
MSGDTA('Rilevato errore durante +
l''esecuzione della procedura, vedere +
messaggi precedenti') MSGTYPE(*ESCAPE)
MONMSG MSGID(CPF0000)
ENDDO
ELSE CMD(IF COND(&E) THEN(DO))
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) +
MSGDTA('Spooled files rimossi +
parzialmente, vedere messaggi +
precedenti') MSGTYPE(*ESCAPE)
MONMSG MSGID(CPF0000)
ENDDO
RETURN
RTVTOTJOBS: SUBR SUBR(RTVTOTJOBS)
DLTF FILE(&SQLLIB/&SQLFIL)
MONMSG MSGID(CPF2105)
CHGVAR VAR(&SQL) VALUE('SELECT TOTAL_JOBS_IN_SYSTEM, +
MAXIMUM_JOBS_IN_SYSTEM FROM +
QSYS2.SYSTEM_STATUS_INFO_BASIC')
CHGVAR VAR(&SQL) VALUE('CREATE TABLE' *BCAT &SQLLIB +
*TCAT '/' *CAT &SQLFIL *BCAT 'AS (' *CAT &SQL +
*TCAT ') WITH DATA')
RUNSQL SQL(&SQL) COMMIT(*NONE) NAMING(*SYS)
MONMSG MSGID(SQL0000) EXEC(DO)
ENDDO
OVRDBF FILE(SQLOUT) TOFILE(&SQLLIB/&SQLFIL) +
MBR(&SQLMBR) LVLCHK(*NO) OVRSCOPE(*CALLLVL)
RCVF OPNID(SQLOUT)
CLOSE OPNID(SQLOUT) /* RVCF */
DLTOVR FILE(SQLOUT) LVL(*) /* OVRDBF */
SNDPGMMSG MSGID(CPI8859) MSGF(QCPFMSG) MSGDTA('Jobs in +
system:' *BCAT %CHAR(&SQLOUT_TOTAL_JOBS) +
*BCAT '/' *BCAT %CHAR(&SQLOUT_MAX_JOBS)) +
TOPGMQ(*PRV) TOMSGQ(*TOPGMQ) MSGTYPE(*INFO)
DLTF FILE(&SQLLIB/&SQLFIL)
MONMSG MSGID(CPF0000)
ENDSUBR RTNVAL(0)
ENDPGM:
ENDPGM
Riferimenti
L’estensione “RPG IV to Free Format Conversion” sviluppata da Bob Cozzi (Cozzi Research) è pensata per semplificare la conversione di…
Ciao a tutti, oggi voglio segnalarvi un altro interessante contributo di Massimo Duca, parte della sua ormai nota serie IBM…
Incuriosito da alcuni messaggi di Cristian Larsen su Linkedin (New Release - Display File DDS Edit v.0.10.1) ho voluto scaricare…
Ciao a tutti,oggi voglio segnalarvi un annuncio che potrebbe segnare una svolta per lo sviluppo applicativo su ambienti IBM: Project…
Voglio segnalarvi un nuovo articolo molto interessante di Massimo Duca nella serie IBM i & SQL Tips. In questo sesto…
Ciao a tutti, voglio segnalarvi un post molto utile di Marco Riva sul suo sito Markonetools, in cui spiega in…