//BCHJOB JOB(JWIATS) JOBD(QBATCH) OUTQ(QPRINT) ENDSEV(60) + LOG(4 00 *SECLVL) MSGQ(*USRPRF) /* Open source scaricabile da www.neroni.it di Claudio Neroni */ /* SE L'USO DELLA JOB DESCRIPTION "QBATCH" TI E' IMPEDITO, */ /* UTILIZZANE UNA DIVERSA. */ /* From System: "IUBICSVI" */ /* From Library: "UTI" */ /* Unload Time: 2009-02-23 10:56 */ /* To File : "JWIATS" */ /* To Library : "NERONI2" */ /* To Text : "Who Is Abusing The System? Src" */ /********* INIZIO ISTRUZIONI *******************************************/ /* LE SUCCESSIVE ISTRUZIONI PERMETTONO DI RICARICARE I SORGENTI. */ /* 1) DA UN VIDEO COMANDI DELL'AS400 RICEVENTE */ /* CREARE UN FILE SORGENTE DI LUNGHEZZA RECORD 112: */ /* CRTSRCPF FILE(NERONI2/STRINGHE) RCDLEN(112) */ /* 2) SPOSTARE IL FILE "JWIATS.txt" NELL'INDIRIZZARIO */ /* DI UN PC CONNESSO IN RETE CON L'AS400 RICEVENTE */ /* (AD ES.: "c:\"). */ /* 3) DAL VIDEO COMANDI DEL PC CHIAMARE FTP: */ /* ftp nomeas400 */ /* 4) DIGITARE UTENTE E PASSWORD. */ /* 5) ESEGUIRE IL COMANDO DI COPIA DA FILE PC A MEMBRO AS400: */ /* put "c:\JWIATS.txt" "/qsys.lib/NERONI2.lib/stringhe.file/JWIATS.mbr"*/ /* 6) ABBANDONARE FTP: */ /* quit */ /* 7) DA UN VIDEO COMANDI DELL'AS400 RICEVENTE */ /* ESEGUIRE LA STRINGA COPIATA NEL MEMBRO SORGENTE: */ /* SBMDBJOB FILE(NERONI2/STRINGHE) MBR(JWIATS) JOBQ(QBATCH) */ /* LE SUCCESSIVE ISTRUZIONI PERMETTONO DI CREARE L'UTILITY. */ /* 8) DA UN VIDEO COMANDI DELL'AS400 RICEVENTE */ /* ESEGUIRE LA STRINGA O LE STRINGHE SORGENTE DI TIPO SEU "CL" */ /* (IL CUI NOME TERMINA SEMPRE CON ".") */ /* PRESENTI NEL FILE RICARICATO "NERONI2/JWIATS" */ /* FACENDO ATTENZIONE ALL'ORDINE DI ESECUZIONE INDICATO NEL */ /* MEMBRO FACOLTATIVO "A.LEGGIMI", AD ESEMPIO: */ /* SBMDBJOB FILE(NERONI2/JWIATS) MBR(JWIATS.) JOBQ(QBATCH) */ /********* FINE ISTRUZIONI *********************************************/ /* Crea la libreria. */ MKDIR DIR('/qsys.lib/NERONI2.lib') CHGLIB LIB(NERONI2) TEXT('Utility di Claudio Neroni') /* Imposta la lista librerie. */ CHGLIBL LIBL(QTEMP NERONI2 QGPL) /* Crea il file sorgente. */ DLTF FILE(NERONI2/JWIATS) CRTSRCPF FILE(NERONI2/JWIATS) RCDLEN(112) + TEXT('Who Is Abusing The System? Src') /* Copia il sorgente dalla stringa al membro del file sorgente. */ /* Modifica testo e tipo seu del sorgente caricato. */ CPYF FROMFILE(JWIATS) TOFILE(NERONI2/JWIATS) + TOMBR(JWIATS) MBROPT(*REPLACE) SRCOPT(*SEQNBR) CHGPFM FILE(NERONI2/JWIATS) MBR(JWIATS) + SRCTYPE(RPGLE) + TEXT('Who Is Abusing The System? Exe') /*---------------------------------------------------------------------*/ //DATA FILE(JWIATS) FILETYPE(*SRC) ENDCHAR('//ENDSRC') /TITLE Who Is Abusing The System? Exe * www.as400pro.com/tipView/category/API/key/723/ ** ** Program . . : CBX102 ** Description : Finds interactive CPU hogs and notifies caller ** Author . . : Carsten Flensburg ** Published . : Club Tech iSeries Programming Tips Newsletter ** Date . . . : June 19, 2003 ** ** ** Program summary ** --------------- ** ** Work management APIs: ** QGYOLJOB Open list of jobs Lists jobs on the system based on ** the specified selection criteria. ** ** Optionally a sort order for the ** returned jobs can be specified - ** in this case the processor unit ** time percentage in descending ** order - listing the jobs having ** the highest CPU usage first. ** ** The CPU processor time is measured ** for an interval of 10 seconds in ** this example. ** ** The QGYOLJOB API is found in the ** QGY library as are all other open ** list APIs. ** ** QWVRCSTK Retrieve Call Stack Lists the program call stack for ** the specified job or thread. ** The current invocation level is ** returned first. ** ** Message handling API: ** QMHSNDM Send message Sends a message to the specified ** non-program message queue - here ** an informational message is sent ** to the current user running this ** program. ** ** Open list APIs: ** QGYGTLE Get list entries To retrieve open lists entries ** from an already open list the ** QGYGTLE (Get List Entries) API ** is available. ** ** QGYCLST Close list This API closes the previously ** opened list identified by the ** request handle parameter. ** Storage allocated is freed. ** ** MI builtins: ** _MATRMD Materialize resource Retrieves processor utilization ** management data data - interactive processor time ** limit. ** ** _MEMMOVE Copy memory Copies a string from one pointer ** specified location to another. ** ** Unix Type - Signal APIs: ** Sleep Suspends program processing for ** the specified number of seconds. ** ** ** Sequence of events: ** 1. The interactive processor time limit percentage is retrieved ** ** 2. The list jobs API input parameters are initialized ** ** 3. The open list of jobs API is called to reset the job ** statistics. ** ** 4. Program is suspended for 10 seconds ** ** 5. The open list of jobs API is called to list the interactive ** jobs on the system returning the most CPU intensive jobs ** for the elapsed period first. ** ** 6. For each job having used more than 50 % of the available ** interactive processor resources a message is sent to the ** message queue of the user currently running the program. ** ** If no jobs are exceeding the above CPU limit a completion ** message is sent, specifying the interactive job having the ** highest CPU utilization. ** ** 7. The job list resources are cleaned up. ** ** ** Programmer's notes: ** Earliest release program will run: V5R1 ** ** As mentioned above library QGY must be in the job library list ** to succesfully run this program. ** ** To retrieve another job's call stack *JOBCTL special authority is ** required. ** ** ** Compile options: ** ** CrtRpgMod Module( CBX102 ) DbgView( *LIST ) ** ** CrtPgm Pgm( CBX102 ) ** Module( CBX102 ) ** ** **-- Control spec: -----------------------------------------------------** H Option( *SrcStmt ) DecEdit( *JobRun ) BndDir( 'QC2LE' ) H DFTACTGRP(*NO) **-- System information: -----------------------------------------------** D PgmSts SDs D PsPgmNam *Proc D PsSts 5a Overlay( PgmSts: 11 ) D PsCurJob 10a Overlay( PgmSts: 244 ) D PsUsrPrf 10a Overlay( PgmSts: 254 ) D PsJobNbr 6a Overlay( PgmSts: 264 ) D PsCurUsr 10a Overlay( PgmSts: 358 ) **-- API error data structure: -----------------------------------------** D ApiError Ds D AeBytPrv 10i 0 Inz( %Size( ApiError )) D AeBytAvl 10i 0 D AeExcpId 7a D 1a D AeExcpDta 128a **-- API parameters: ---------------------------------------------------** D JlRtnRcdNbr s 10i 0 Inz( 1 ) D JlNbrFldRtn s 10i 0 Inz( %Elem( JlKeyFld )) D JlKeyFld s 10i 0 Dim( 3 ) **-- Job information: D JlJobInf Ds 512 D JbJobId 26a D JbJobUsd 10a Overlay( JbJobId: 1 ) D JbUsrUsd 10a Overlay( JbJobId: *Next ) D JbNbrUsd 6a Overlay( JbJobId: *Next ) D JbActSts 4a D JbJobTyp 1a D JbJobSubTyp 1a D JbDtaLen 10i 0 D 4a D JbDta 256a **-- Key information: D JlKeyInf Ds D KiFldNbrRtn 10i 0 D KiKeyInf 20a Dim( %Elem( JlKeyFld )) D KiFldInfLen 10i 0 Overlay( KiKeyInf : 1 ) D KiKeyFld 10i 0 Overlay( KiKeyInf : 5 ) D KiDtaTyp 1a Overlay( KiKeyInf : 9 ) D 3a Overlay( KiKeyInf : 10 ) D KiDtaLen 10i 0 Overlay( KiKeyInf : 13 ) D KiDtaOfs 10i 0 Overlay( KiKeyInf : 17 ) **-- Sort information: D JlSrtInf Ds D SiNbrKeys 10i 0 Inz( 1 ) D SiSrtInf 12a Dim( 10 ) D SiKeyFldOfs 10i 0 Overlay( SiSrtInf : 1 ) D SiKeyFldLen 10i 0 Overlay( SiSrtInf : 5 ) D SiKeyFldTyp 5i 0 Overlay( SiSrtInf : 9 ) D SiSrtOrd 1a Overlay( SiSrtInf : 11 ) D SiRsv 1a Overlay( SiSrtInf : 12 ) **-- List information: D JlLstInf Ds D LiRcdNbrTot 10i 0 D LiRcdNbrRtn 10i 0 D LiHandle 4a D LiRcdLen 10i 0 D LiInfSts 1a D LiDts 13a D LiLstSts 1a D 1a D LiInfLen 10i 0 D LiRcd1 10i 0 D 40a **-- Selection information: D JlSltInf Ds D SiJobNam 10a Inz( '*ALL' ) D SiUsrNam 10a Inz( '*ALL' ) D SiJobNbr 6a Inz( '*ALL' ) D SiJobTyp 1a Inz( 'I' ) D 1a D SiOfsPriSts 10i 0 Inz( 60 ) D SiNbrPriSts 10i 0 Inz( 0 ) D SiOfsActSts 10i 0 Inz( 70 ) D SiNbrActSts 10i 0 Inz( 0 ) D SiOfsJbqSts 10i 0 Inz( 78 ) D SiNbrJbqSts 10i 0 Inz( 0 ) D SiOfsJbqNam 10i 0 Inz( 88 ) D SiNbrJbqNam 10i 0 Inz( 0 ) ** D SiPriSts 10a Dim( 1 ) D SiActSts 4a Dim( 2 ) D SiJbqSts 10a Dim( 1 ) D SiJbqNam 20a Dim( 1 ) **-- Job information key fields: D JbKeyDta Ds D JbPrcUniTim 20u 0 D JbPrcUniPct 9b 1 D JbPrcUniTimE 20u 0 **-- General return data: D JlGenDta Ds D GdBytRtn 10i 0 D GdBytAvl 10i 0 D GdElpTim 20u 0 D 16a **-- MatRmd parameters: ------------------------------------------------** D MatRscMgDt Ds D RdBytPrv 10i 0 Inz( %Size( MatRscMgDt )) D RdBytAvl 10i 0 D RdTimDay 8a D RdData D RdPrcTimIpl 20u 0 Overlay( RdData: 1 ) D RdPrcTimScWl 20u 0 Overlay( RdData: *Next ) D RdPrcTimDb 20u 0 Overlay( RdData: *Next ) D RdPrcTimDbTh 5u 0 Overlay( RdData: *Next ) D RdPrcTimDbLm 5u 0 Overlay( RdData: *Next ) D RdRsv1 10u 0 Inz( x'00' ) D Overlay( RdData: *Next ) D RdPrcTimInt 20u 0 Overlay( RdData: *Next ) D RdPrcTimIntT 4b 1 Overlay( RdData: *Next ) D RdPrcTimIntL 4b 1 Overlay( RdData: *Next ) D RdRsv2 10u 0 Inz( x'00' ) D Overlay( RdData: *Next ) ** D MatCtlDta Ds D CdSltOpt 1a Inz( x'01' ) D CdRsv 7a Inz( *Allx'00' ) **-- Global variables: -------------------------------------------------** D Ix s 5i 0 D CpuLvl s 5i 0 D PgmNam s 10a D MsgDta s 256a Varying D MsgKey s 4a **-- API constants: ----------------------------------------------------** D JOB_RESET_STAT c '1' D JOB_KEEP_STAT c '0' **-- Open list of jobs: ------------------------------------------------** D LstJobs Pr ExtPgm( 'QGYOLJOB' ) D LjRcvVar 65535a Options( *VarSize ) D LjRcvVarLen 10i 0 Const D LjFmtNam 8a Const D LjRcvVarDfn 65535a Options( *VarSize ) D LjRcvDfnLen 10i 0 Const D LjLstInf 80a D LjNbrRcdRtn 10i 0 Const D LjSrtInf 1024a Const Options( *VarSize ) D LjJobSltInf 1024a Const Options( *VarSize ) D LjJobSltLen 10i 0 Const D LjNbrFldRtn 10i 0 Const D LjKeyFldRtn 10i 0 Const Options( *VarSize ) Dim( 32 ) D LjError 1024a Options( *VarSize ) ** D LjJobSltFmt 8a Const Options( *NoPass ) ** D LjResStc 1a Const Options( *NoPass ) D LjGenRtnDta 32a Options( *NoPass: *VarSize ) D LjGenRtnDtaLn 10i 0 Const Options( *NoPass ) **-- Get list entry: ---------------------------------------------------** D GetLstEnt Pr ExtPgm( 'QGYGTLE' ) D GlRcvVar 65535a Options( *VarSize ) D GlRcvVarLen 10i 0 Const D GlHandle 4a Const D GlLstInf 80a D GlNbrRcdRtn 10i 0 Const D GlRtnRcdNbr 10i 0 Const D GlError 1024a Options( *VarSize ) **-- Close list: -------------------------------------------------------** D CloseLst Pr ExtPgm( 'QGYCLST' ) D ClHandle 4a Const D ClError 1024a Options( *VarSize ) **-- Send message: -----------------------------------------------------** D SndMsg Pr ExtPgm( 'QMHSNDM' ) D SmMsgId 7a Const D SmMsgFq 20a Const D SmMsgDta 512a Const Options( *VarSize ) D SmMsgDtaLen 10i 0 Const D SmMsgTyp 10a Const D SmMsgQq 1000a Const Options( *VarSize ) D SmMsgQnbr 10i 0 Const D SmMsgQrpy 20a Const D SmMsgKey 4a D SmError 10i 0 Const ** D SmCcsId 10i 0 Const Options( *NoPass ) **-- Copy memory: ------------------------------------------------------** D memcpy Pr * ExtProc( '_MEMMOVE' ) D outmem * Value D inpmem * Value D memsiz 10u 0 Value **-- Delay job: --------------------------------------------------------** D sleep Pr 10i 0 ExtProc( 'sleep' ) D seconds 10u 0 Value **-- Get top stack entry: ----------------------------------------------** D GetTopStkE Pr 20a D GtJobId 26a Const **-- Materialize resource management data: -----------------------------** D MatRmd Pr ExtProc( '_MATRMD' ) D Rcv Like( MatRscMgDt ) D Ctl Like( MatCtlDta ) ** **-- Mainline: ---------------------------------------------------------** ** **-- Get interactive processor time limit: C Callp(e) MatRmd( MatRscMgDt: MatCtlDta ) ** C If %Error C Eval RdPrcTimIntL= 100 C EndIf ** **-- Job information return fields: C Eval JlKeyFld(1) = 312 C Eval JlKeyFld(2) = 314 C Eval JlKeyFld(3) = 315 ** **-- Sort field specification: C Eval SiNbrKeys = 1 C Eval SiKeyFldOfs(1) = 49 C Eval SiKeyFldLen(1) = 4 C Eval SiKeyFldTyp(1) = 0 C Eval SiSrtOrd(1) = '2' C Eval SiRsv(1) = x'00' ** **-- Initialize job CPU measurement: **-- NOTE: Statistics only reset if return records are requested ** C CallP LstJobs( JlJobInf C : %Size( JlJobInf ) C : 'OLJB0300' C : JlKeyInf C : %Size( JlKeyInf ) C : JlLstInf C : 1 C : JlSrtInf C : JlSltInf C : %Size( JlSltInf ) C : JlNbrFldRtn C : JlKeyFld C : ApiError C : 'OLJS0100' C : JOB_RESET_STAT C : JlGenDta C : %Size( JlGenDta ) C ) ** **-- Wait 10 seconds: C CallP sleep( 10 ) ** **-- Retrieve job list: C CallP LstJobs( JlJobInf C : %Size( JlJobInf ) C : 'OLJB0300' C : JlKeyInf C : %Size( JlKeyInf ) C : JlLstInf C : 1 C : JlSrtInf C : JlSltInf C : %Size( JlSltInf ) C : JlNbrFldRtn C : JlKeyFld C : ApiError C : 'OLJS0100' C : JOB_KEEP_STAT C : JlGenDta C : %Size( JlGenDta ) C ) ** C If AeBytAvl = *Zero ** C DoW LiLstSts <> '2' Or C LiRcdNbrTot > JlRtnRcdNbr ** C ExSr GetCpuDta C ExSr ChkCpuPct ** C If CpuLvl = 2 C ExSr SndCmpMsg C EndIf ** C If CpuLvl >= 2 C Leave C EndIf ** C Eval JlRtnRcdNbr = JlRtnRcdNbr + 1 ** C CallP GetLstEnt( JlJobInf C : %Size( JlJobInf ) C : LiHandle C : JlLstInf C : 1 C : JlRtnRcdNbr C : ApiError C ) ** C If AeBytAvl > *Zero C Leave C EndIf ** C EndDo ** C CallP CloseLst( LiHandle C : ApiError C ) ** C EndIf ** C Eval *InLr = *On ** C Return ** **-- Get CPU data: -----------------------------------------------------** C GetCpuDta BegSr ** C Clear JbKeyDta ** C For Ix = 1 To KiFldNbrRtn ** C Select C When KiKeyFld(Ix) = 312 C CallP memcpy( %Addr( JbPrcUniTim ) C : %Addr( JlJobInf ) + C KiDtaOfs(Ix) C : KiDtaLen(Ix) C ) ** C When KiKeyFld(Ix) = 314 C CallP memcpy( %Addr( JbPrcUniPct ) C : %Addr( JlJobInf ) + C KiDtaOfs(Ix) C : KiDtaLen(Ix) C ) ** C When KiKeyFld(Ix) = 315 C CallP memcpy( %Addr( JbPrcUniTimE ) C : %Addr( JlJobInf ) + C KiDtaOfs(Ix) C : KiDtaLen(Ix) C ) C EndSl C EndFor ** C EndSr **-- Check CPU percent: ------------------------------------------------** C ChkCpuPct BegSr ** C If JbPrcUniPct > RdPrcTimIntL / 2 ** C Eval CpuLvl = 1 C Eval PgmNam = GetTopStkE( JbJobId ) ** C Eval MsgDta = 'CPU alert - program ' + C %Trim( PgmNam ) + C ' in job ' + C %Trim( JbJobUsd ) + C ' is currently using ' + C %Char( JbPrcUniPct ) + C ' CPU % of ' + C %Char( RdPrcTimIntL ) + C ' interactive CPU % available.' ** C CallP(e) SndMsg( *Blanks C : *Blanks C : MsgDta C : %Len( MsgDta ) C : '*INFO' C : PsCurUsr + '*LIBL' C : 1 C : *Blanks C : MsgKey C : 0 C ) ** C Else C Eval CpuLvl = CpuLvl + 2 C EndIf ** C EndSr **-- Send completion message: ------------------------------------------** C SndCmpMsg BegSr ** C Eval MsgDta = 'CPU monitor completed ' + C '- max utilization by job ' + C %Trim( JbJobUsd ) + C ' using ' + C %Char( JbPrcUniPct ) + C ' CPU % of ' + C %Char( RdPrcTimIntL ) + C ' interactive CPU % available.' ** C CallP(e) SndMsg( *Blanks C : *Blanks C : MsgDta C : %Len( MsgDta ) C : '*COMP' C : PsCurUsr + '*LIBL' C : 1 C : *Blanks C : MsgKey C : 0 C ) ** C EndSr **-- Get top stack entry: ----------------------------------------------** P GetTopStkE B Export D Pi 20a D GtJobId 26a Const **-- API parameters: D CsRcvVar Ds D CsBytRtn 10i 0 D CsBytAvl 10i 0 D CsNbrStkE 10i 0 D CsOfsStkE 10i 0 D CsNbrEntRtn 10i 0 D CsThrId 8a D CsInfSts 1a D CsCalStk 32767a ** D CsCalStkE Ds Based( pCalStkE ) D CsStkEntLen 10i 0 D CsOfsStmIds 10i 0 D CsNbrStmIds 10i 0 D CsOfsPrcNam 10i 0 D CsLenPrcNam 10i 0 D CsRqsLvl 10i 0 D CsPgmNam 10a D CsPgmLib 10a D CsMiInst 10i 0 D CsModNam 10a D CsModLib 10a D CsCtlBdy 1a D CsRsv 3a D CsActGrpNbr 10u 0 D CsActGrpNam 10a D CsAddInf 4096a ** D CsStmIds 10a Dim( 16 ) D CsPrcNam 512a ** D CsJobId Ds D JiJobId 26a D JiJobNam 10a Overlay( JiJobId: 1 ) D JiUsrNam 10a Overlay( JiJobId: *Next ) D JiJobNbr 6a Overlay( JiJobId: *Next ) D JiIntId 16a D JiRsv 2a Inz( *Allx'00' ) D JiThrInd 10i 0 Inz( 2 ) D JiThrId 8a Inz( *Allx'00' ) **-- Retrieve call stack: D RtvCalStk Pr ExtPgm( 'QWVRCSTK' ) D RcRcvVar 32767a D RcRcvVarLen 10i 0 Const D RcRcvInfFmt 8a Const D RcJobId 56a Const D RcJobIdFmt 8a Const D RcError 32767a Options( *VarSize ) ** D EntNbr s 5u 0 **-- Get stack entries: ------------------------------------------------** ** C Eval JiJobId = GtJobId ** C CallP RtvCalStk( CsRcvVar C : %Size( CsRcvVar ) C : 'CSTK0100' C : CsJobId C : 'JIDF0100' C : ApiError C ) ** C If AeBytAvl = *Zero C Eval pCalStkE = %Addr( CsRcvVar ) + CsOfsStkE ** C For EntNbr = 1 to CsNbrEntRtn ** C If EntNbr = 1 ** C Eval CsStmIds = *Blanks C Eval CsPrcNam = *Blanks ** C If CsOfsStmIds > *Zero C CallP MemCpy( %Addr( CsStmIds ) C : %Addr( CsCalStkE ) + C CsOfsStmIds C : CsNbrStmIds * %Size( CsStmIds ) C ) C EndIf ** C If CsOfsPrcNam > *Zero C CallP MemCpy( %Addr( CsPrcNam ) C : %Addr( CsCalStkE ) + C CsOfsPrcNam C : CsLenPrcNam C ) C EndIf ** C Leave C EndIf ** C If EntNbr < CsNbrEntRtn C Eval pCalStkE = PCalStkE + CsStkEntLen C EndIf C EndFor ** C Return CsPgmNam + CsPgmLib ** C Else C Return *Blanks C EndIf ** P GetTopStkE E //ENDSRC //ENDBCHJOB