H DATEDIT(*YMD) DEBUG(*YES) OPTION(*NODEBUGIO : *SRCSTMT) DFTACTGRP(*NO)
H COPYRIGHT('Copyright (C) 2003 Martin Rowe <martin@dbg400.net>')
**********************************************************************************************
* DBG205R4: DASD monitor
* Copyright (C) 2003 Martin Rowe <martin@dbg400.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
**********************************************************************************************
* FILES:
**********************************************************************************************
**********************************************************************************************
* PROTOTYPES:
**********************************************************************************************
D RunCmd PR 1N
D Command 999 Options(*VARSIZE) Const
**********************************************************************************************
* ARRAYS:
**********************************************************************************************
* Message queue array
D P_MsgQueue S 20 Dim(50)
**********************************************************************************************
* DATA STRUCTURES:
**********************************************************************************************
D SDS
D SDS_Pgm 10
* Receiver value DS
D RcvrDS DS 68
D BytesAvail 10I 0
D BytesReturned 10I 0
D CurDateTime 8
D SystemName 8
D ElapsedTime 6
D RetrictState 1
D Reserved1 1
D PctProcUnit 10I 0
D JobsInSystem 10I 0
D PctPermAddr 10I 0
D PctTempAddr 10I 0
D SystemASP 10I 0
D PctSystemASP 10I 0
D TotAuxStorage 10I 0
D CurUnProStg 10I 0
D MaxUnProStg 10I 0
* Standard error code DS for API error handling
D Error_Code DS 272
D ErrBytesProvd 10I 0 Inz(0)
D ErrBytesAvail 10I 0 Inz(0)
D ErrExcept_ID 7
D ErrReserved 1
D ErrException 256
* Receiver value DS for user space header info (used in first call to QUSRTVUS)
D GenRcvrDS DS
D UserArea 64
D GenHdrSize 10I 0
D StrucLevel 4
D FormatName 8
D APIUsed 10
D CreateStamp 13
D InfoStatus 1
D SizeUsUsed 10I 0
D InpParmOff 10I 0
D InpParmSiz 10I 0
D HeadOffset 10I 0
D HeaderSize 10I 0
D ListOffset 10I 0
D ListSize 10I 0
D ListNumber 10I 0
D EntrySize 10I 0
* Type Definition for the JOBL0200 format.
D ListDataDS DS
D L_JobName 10
D L_JobUser 10
D L_JobNbr 6
D L_JobIdent 16
D L_Status 10
D L_JobType 1
D L_JobSubTy 1
D L_Reserved 2
D L_JobInfoSts 1
D L_Reserved2 3
D L_NbrFldsRtn 10I 0
* Repeated section for each key
D L_Variable 2000
*
D Key1Info DS 20
D L_LenInfoRtn1 10I 0
D L_KeyFld1 10I 0
D L_DataType1 1
D L_Reservedx1 3
D L_LenDataRtn1 10I 0
D L_KeyValue1 10I 0
*
D Key2Info DS 20
D L_LenInfoRtn2 10I 0
D L_KeyFld2 10I 0
D L_DataType2 1
D L_Reservedx2 3
D L_LenDataRtn2 10I 0
D L_KeyValue2 4
* Message queue definition
D DS
D MsgQueue 20
D MsgQueName 10 Overlay(MsgQueue)
D MsgQueLib 10 Overlay(MsgQueue:11)
*
D PackAsChar DS
D PackedFld1 3P 0
D CharFld1 2 Overlay(PackedFld1)
**********************************************************************************************
* WORK FIELDS:
**********************************************************************************************
D Cumulative S 7 4
D CurrentEnt S 5P 0 Inz(1)
D DataLength S 10I 0 Inz(140)
D Difference S 7 4
D ExtendAttr S 10 Inz('USRSPC ')
D FirstTime S 1N Inz(*On)
D Flag S 3
D Format S 8
D Index S 10I 0
D InitialSiz S 10I 0 Inz(1024)
D InitialVal S 1 Inz(X'00')
D JobStatus S 10 Inz('*ACTIVE ')
D JobType S 1 Inz('*')
D KeyOffSet S 10I 0
D KeysToRtn S 10I 0 Dim(2)
D ListFormat S 8 Inz('JOBL0200')
D NbrToRtn S 10I 0 Inz(2)
D P_DtaqData S 1
D P_DtaqLen S 5 0
D P_DtaqLib S 10
D P_DtaqName S 10
D P_DtaqWait S 5 0
D P_ErrorID S 7
D P_MsgData S 512
D P_MsgDtaLn S 5 0
D P_MsgFile S 10
D P_MsgID S 7
D P_MsgQueLn S 5 0
D P_MsgType S 10
D P_MsgfLib S 10
D P_RplyMsgQ S 20
D peDiskIncrease S 5 2
D peDiskUse S 3 0
D peFrequency S 3 0
D peTempStorage S 5 0
D Percentage S 7 4
D PrevDiff S 7 4
D PrevPercent S 7 4
D PublicAut S 10 Inz('*ALL ')
D QualifyJob S 26 Inz('*ALL *ALL *ALL ')
D QualJob S 28 Varying
D RCVRLen S 10I 0
D ReplaceSpc S 10 Inz('*YES ')
D RstStsStat S 10
D SubstOffset S 10I 0 Inz(1)
D StartPos S 10I 0 Inz(1)
D TextDescrp S 50 Inz('User space for List Job API')
D ThresholdMb S 10I 0
D UserSpace S 20 Inz('DASDMON QTEMP ')
D MessageUsers S 50 DtaAra(DASDMON)
D WarnLevel S 2 0
**********************************************************************************************
* CONSTANTS:
**********************************************************************************************
D ActiveJobSts C Const(0101)
D TempStorage C Const(2009)
**********************************************************************************************
* FIELD RENAMES:
**********************************************************************************************
**********************************************************************************************
* ENTRY PARAMETERS:
**********************************************************************************************
C *entry PList
C Parm peFrequency
C Parm peDiskUse
C Parm peDiskIncrease
C Parm peTempStorage
**********************************************************************************************
* KEY LISTS:
**********************************************************************************************
**********************************************************************************************
* MAINLINE:
**********************************************************************************************
* Set program control from input parms
C Eval WarnLevel = peDiskUse
C Eval ThresholdMb = peTempStorage
C In MessageUsers
* Create a user space to hold the job list entries
C Call 'QUSCRTUS'
C Parm UserSpace
C Parm ExtendAttr
C Parm InitialSiz
C Parm InitialVal
C Parm PublicAut
C Parm TextDescrp
C Parm ReplaceSpc
C Parm Error_Code
*
B001 C Do *hival
* Do system status check first
C Call 'QWCRSSTS' 90
C Parm RcvrDS
C Parm 68 RCVRLen
C Parm 'SSTS0200' Format
C Parm '*NO' RstStsStat
C Parm Error_Code
* Set prev values for first time through (no need to warn in that case)
B002 C If FirstTime
C Eval PrevPercent = PctSystemASP / 10000
C Eval FirstTime = *Off
E002 C EndIf
C Eval Percentage = PctSystemASP / 10000
C Eval Difference = Percentage - PrevPercent
C Eval Cumulative = PrevDiff + Difference
B002 C If Cumulative > peDiskIncrease
C Or Difference > (peDiskIncrease / 2)
C Eval Flag = '***'
X002 C Else
C Eval Flag = ' '
E002 C EndIf
C Eval P_MsgData = 'System DASD used: ' +
C %Trim(%EditC(Percentage:'P')) +
C '%. Change since last check: ' +
C %Trim(%EditC(Difference:'P')) + '%' + Flag
* Place current DASD % and increase/decrease since last check in the audit log
C Clear P_MsgQueue
C Eval MsgQueName = 'DASDMON'
C Eval MsgQueLib = '*LIBL'
C Eval P_MsgQueue(1) = MsgQueue
C Eval P_MsgQueLn = 1
C ExSr Inform
* Warn if significant rise since last time
B002 C If Cumulative > peDiskIncrease
C Or Difference > (peDiskIncrease / 2)
C Eval P_MsgData = 'System storage use is ' +
C 'increasing. DSPMSG DASDMON to check.'
C ExSr SetMsgUsers
C ExSr Inform
E002 C EndIf
* Warn if over xx% storage
B002 C If Percentage > WarnLevel
C Eval P_MsgData = 'System storage over ' +
C %Char(WarnLevel) +
C '%. DSPMSG DASDMON to review history.'
C ExSr SetMsgUsers
C ExSr Inform
E002 C EndIf
C Eval PrevPercent = Percentage
C Eval PrevDiff = Difference
* Monitor for any jobs using too much temporary storage
C Eval KeysToRtn(1) = TempStorage
C Eval KeysToRtn(2) = ActiveJobSts
* List all the *ACTIVE jobs on the system
C Call 'QUSLJOB'
C Parm UserSpace
C Parm ListFormat
C Parm QualifyJob
C Parm JobStatus
C Parm Error_Code
C Parm JobType
C Parm NbrToRtn
C Parm KeysToRtn
* Get the header info for this space
C Call 'QUSRTVUS'
C Parm UserSpace
C Parm StartPos
C Parm DataLength
C Parm GenRcvrDS
C Parm Error_Code
* Check to see how many entries returned (ie. number of active jobs)
B002 C If ListNumber > 0
* Set the initial offset for the start of the list entries
C Eval ListOffset = ListOffset + 1
C Eval CurrentEnt = 1
* Loop through the entries held in the list section of the user space
B003 C DoW CurrentEnt <= ListNumber
* Get the header info for this space
C Call 'QUSRTVUS'
C Parm UserSpace
C Parm ListOffset
C Parm EntrySize
C Parm ListDataDS
C Parm Error_Code
* Get first key data
C Eval KeyOffSet = 1
C Eval Key1Info = %SubSt(L_Variable :
C KeyOffSet : 20)
* Get second key data
C Eval KeyOffSet = KeyOffSet + L_LenInfoRtn1
C Eval Key2Info = %SubSt(L_Variable :
C KeyOffSet : 20)
*
B004 C If L_KeyValue1 > ThresholdMb
C Eval QualJob = L_JobNbr + '/' +
C %Trim(L_JobUser) + '/' + %Trim(L_JobName)
* Hold job if using more than xxxx temp storage
B005 C If L_KeyValue2 <> 'HLD '
C CallP RunCmd('HLDJOB JOB(' + QualJob + ')')
C Eval P_MsgData = 'Job ' + L_JobNbr + '/' +
C %Trim(L_JobUser) + '/' + %Trim(L_JobName) +
C ' held.'
C ExSr SetMsgUsers
C ExSr Inform
E005 C EndIf
C Eval P_MsgData = 'Job ' + L_JobNbr + '/' +
C %Trim(L_JobUser) + '/' + %Trim(L_JobName) +
C ' has temporary storage of ' +
C %Trim(%EditC(L_KeyValue1: 'Z')) + 'Mb. '
C ExSr SetMsgUsers
C ExSr Inform
E004 C EndIf
* Bump up the counter & offset for the next entry
C Eval ListOffset = ListOffset + EntrySize
C Eval CurrentEnt = CurrentEnt + 1
E003 C EndDo
E002 C EndIf
* Wait x minutes before taking the next snapshot unless exit request received
C Eval P_DtaqWait = peFrequency * 60
C Call 'QRCVDTAQ'
C Parm 'DASDMON' P_DtaqName
C Parm '*LIBL' P_DtaqLib
C Parm 1 P_DtaqLen
C Parm *blanks P_DtaqData
C Parm P_DtaqWait
* Quit if requested
B002 C If P_DtaqData = 'Y'
C Leave
E002 C EndIf
E001 C EndDo
C Eval *INLR = *On
C Return
**********************************************************************************************
* SetMsgUsers: Set up the list of message queues to receive storage alerts
**********************************************************************************************
C SetMsgUsers BegSr
* Send alert messages to DASDMON & QSYSOPR by default
C Eval MsgQueName = 'DASDMON'
C Eval MsgQueLib = '*LIBL'
C Eval P_MsgQueue(1) = MsgQueue
C Eval P_MsgQueLn = 1
C Eval MsgQueName = 'QSYSOPR'
C Eval MsgQueLib = '*USER'
C Eval P_MsgQueue(2) = MsgQueue
C Eval P_MsgQueLn = 2
* Check for any other users to send alert messages to
B001 C Do 6 Index
B002 C If %SubSt(MessageUsers : SubstOffset : 10)
C <> *blanks
C Eval MsgQueName = %SubSt(MessageUsers :
C SubstOffset : 10)
C Eval MsgQueLib = '*USER'
C Eval P_MsgQueue(Index + 2) = MsgQueue
C Eval P_MsgQueLn = P_MsgQueLn + 1
C Eval SubstOffset = SubstOffset + 10
E002 C EndIf
E001 C EndDo
*
C EndSr
**********************************************************************************************
* Inform: Send Non-Program Message
**********************************************************************************************
C Inform BegSr
*
C Call 'DBG045R3'
C Parm 'CPF9898' P_MsgID
C Parm 'QCPFMSG ' P_MsgFile
C Parm '*LIBL ' P_MsgfLib
C Parm P_MsgData
C Parm 512 P_MsgDtaLn
C Parm '*INFO' P_MsgType
C Parm P_MsgQueue
C Parm P_MsgQueLn
C Parm P_RplyMsgQ
C Parm ' ' P_ErrorID
*
C EndSr
**********************************************************************************************
* PROCEDURES:
**********************************************************************************************
**********************************************************************************************
* RunCmd: Run a command via QCMDEXC & return the error flag
**********************************************************************************************
P RunCmd B
D RunCmd PI 1N
D Command 999 Options(*VARSIZE) Const
D RunCmdError S 1N
D P#CmdString S 999
D P#CmdLength S 15 5
C Eval P#CmdLength = %Len(%TrimR(Command))
C Call (E) 'QCMDEXC'
C Parm Command P#CmdString
C Parm P#CmdLength
C Eval RunCmdError = %ERROR
C Return RunCmdError
P E
**********************************************************************************************