From: tiz@ludens.elte.hu
Sent: Friday, August 17, 2001 7:34 AM
To: Info-VAX@Mvb.Saic.Com
Subject: Re: Is there a Lexical function that shows a process state

In article <tnojeup0uflf78@corp.supernews.com>, "Bill Ames" <billames@accunet.net> writes:

  Hi!

> Here is my pseudo code.

  And here is my non-pseudo code. :)
  I think you can use this program for your problem.
  If you don't want to extract it from news, you can
  download it from

           http://vms.elte.hu/

  Good luck!



Toth, Istvan Zoltan          tiz@ludens elte hu        SYSTEM PROGRAMMER
 ......................................................................
 VMS Competence Center                            VMS Szakertoi Kozpont
 Eotvos Lorand University                 Eotvos Lorand Tudomanyegyetem
 Budapest, Hungary                                             Budapest
 ======================================================================


$!
$! Copyright (C) 2001  ELTE VMS Competence Center (vcc@vms.elte.hu)
$!
$! 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.
$!
$!   PROGRAM:    check_state
$!
$!   ABSTRACT:   This program checks states of processes in the system,
$!               and it sends a mail to the specified user when
$!               a process stays in a specified resource wait state.
$!
$!               To check processes of other users you WORLD privilege
$!               is needed.
$!
$!   USAGE:      Typical usage of check_state is to submit it into a 
$!               queue. To do this you can use the following command.
$!
$!               submit check_state.com /param=("tiz@ludens.elte.hu", -
$!                  "00:00:05.00", "", "RWMBX/00:00:10.00")
$!
$!   PARAMETERS:
$!
$!      P1        :     E-mail address(es) to which messages are sended.
$!      P2        :     Checking interval in delta-time format.
$!      P3        :     Name of log file. If you don't want to log events
$!                      specify "" as P3.
$!      P4 .. P8  :     Watched process states and amount of time while
$!                      process have to stay in the specified state to
$!                      generate warning. You can specify maximum 6
$!                      state to watch. Format of parameters is 
$!
$!                                   "state/delta time"
$!
$!                      For example:
$!
$!                                 "RWMBX / 00:05:00.00"
$!
$!                      This parameters specifies than program have to
$!                      check state RWMBX and when a process stays in
$!                      this state for 5 minutes, check_state have to
$!                      send a mail to specified addresses. 
$!
$!                      You can use the following resource wait state names:
$!
$!                         RWAST  -  AST wait
$!                         RWMBX  -  Mailbox full
$!                         RWNPG  -  Non-paged pool
$!                         RWPFF  -  Page file full
$!                         RWPAG  -  Paged pool
$!                         RWBRK  -  Waiting for BROADCAST to finish
$!                         RWIMG  -  Image activation lock
$!                         RWQUO  -  Pooled quota
$!                         RWLCK  -  Lock ID data base
$!                         RWSWP  -  Swap file space
$!                         RWMPE  -  Modified page list empty
$!                         RWMPB  -  Modified page writer busy
$!                         RWSCS  -  SCS wait
$!                         RWCLU  -  Cluster transition wait
$!                         RWCAP  -  CPU capability required
$!                         RWCSV  -  Cluster server
$!                         RWSNP  -  System snapshot
$!                         PSXFR  -  POSIX fork wait
$!                         RWINS  -  Inner mode (semaphore) wait
$!                         RWEXH  -  'Exit Handling' wait
$!
$!
$
$       on control_y then goto cleanup
$       on error then exit $status
$
$     !
$     ! Initializing variables 
$     !
$       gosub initialize_variables
$
$     !
$     ! Checking parameters
$     !
$       address = f$edit (p1, "collapse")
$       if address .eqs. "" then return 44 ! SS$_BADPARAM
$ 
$       set noon
$       interval = f$cvtime(p2,"DELTA")
$       if .not. $status then exit 44 ! SS$_BADPARAM
$       set on
$
$       if p3 .nes. ""
$       then
$          open/write logfile 'p3'
$          write logfile f$fao("!%D program start", 0)
$       endif

$       idx = 4
$       param_loop:
$          param = p'idx'
$          if param .eqs. ""
$          then
$             idx = idx + 1
$             if idx .lt. 8 then goto param_loop
$             goto param_loop_end
$          endif
$
$          state = f$edit(f$element(0, "/", param),"upcase,collapse")
$          time  = f$edit(f$element(1, "/", param),"compress,trim")
$
$        !
$        ! Checking time
$        !
$          set noon
$          tmp = f$cvtime(time,"DELTA")
$          if .not. $status
$          then
$             call write_log -
                  "Invalid delta time: ''param', parameter ignored. " -
                  "''address'"
               goto param_loop
$          endif
$          set on
$
$        !
$        ! Checking state
$        !
$          idx2 = state_first
$          check_state_loop:
$             if state .eqs. state_'idx2'
$             then
$                stslst         = stslst + f$string(idx2) + ","
$                time_'idx2'    = time
$                goto check_state_loop_end
$             endif
$
$             idx2 = idx2 + 1
$             if idx2 .le. state_last then goto check_state_loop
$             then
$                call write_log -
                    "Unknown process state: ''state', parameter ignored. " -
                    "''address'"
                 goto param_loop
$             endif   
$          check_state_loop_end:
$
$          idx = idx + 1
$          if idx .lt. 8 then goto param_loop
$       param_loop_end:
$
$       stslstlen = f$length(stslst)
$
$     !
$     ! Main loop
$     !  
$       main_loop:
$          ctx       = ""
$          tmp       = f$context("PROCESS", ctx, "STATE", "MWAIT", "EQL")
$          newlst    = ","
$          curtim    = f$cvtime(,"COMPARISON")
$          prclstlen = f$length(prclst)
$
$        !
$        ! Checking specified process states
$        !
$          check_loop:
$             pid = f$pid(ctx)
$             if pid .eqs. "" then goto check_loop_end
$
$             newlst = newlst + pid + ","
$
$             state = f$getjpi(pid,"EFWM")
$             if f$locate(",''state',",stslst) .eq. stslstlen then -
                 goto check_loop
$
$             if f$locate(pid, prclst) .ne. prclstlen
$             then
$                if (chk_'pid'_wartim .lts. curtim) .and. -
                    (chk_'pid'_state .eq. state) .and. -
                    (chk_'pid'_mail .eq. 0)
$                then
$                   ststxt = state_'state'
$                   dettim = chk_'pid'_dettim
$                   call write_log -
                       "Process ''pid' stays in ''ststxt' since ''dettim'." -
                       "''address'"
$                   chk_'pid'_mail = 1
$                endif
$             else
$                time = time_'state'
$                chk_'pid'_wartim =  f$cvtime("+''time'","COMPARISON") 
$                chk_'pid'_dettim =  curtim
$                chk_'pid'_mail   =  0
$                chk_'pid'_state  =  state
$             endif
$
$             goto check_loop
$          check_loop_end:
$
$           ! 
$           ! Deleting symbols of invalid entries in process list
$           !
$          idx      = 0
$          prclst    = prclst - "," 
$          newlstlen = f$length(newlst)
$ 
$          cleanup_loop:
$             pid = f$element(idx,",",prclst)
$             if pid .eqs. "," then goto cleanup_loop_end
$
$             if f$locate(pid,newlst) .eq. newlstlen
$             then
$                delete/symbol chk_'pid'_wartim
$                delete/symbol chk_'pid'_dettim
$                delete/symbol chk_'pid'_mail
$                delete/symbol chk_'pid'_state
$             endif
$             
$             idx = idx + 1
$          cleanup_loop_end:
$ 
$          prclst = newlst
$
$          wait 'interval'
$          goto main_loop
$
$       main_loop_end:
$
$       exit
$
$
$ cleanup:
$       if p3 .nes. "" then close logfile
$       exit
$
$ ! 
$ !  Subroutines
$ !
$
$ initialize_variables:
$
$       prclst       = ","
$       stslst       = ","
$
$       state_first  = 1
$
$       state_1      = "RWAST"          ! AST wait
$       state_2      = "RWMBX"          ! Mailbox full
$       state_3      = "RWNPG"          ! Non-paged pool
$       state_4      = "RWPFF"          ! Page file full
$       state_5      = "RWPAG"          ! Paged pool
$       state_6      = "RWBRK"          ! Waiting for BROADCAST to finish
$       state_7      = "RWIMG"          ! Image activation lock
$       state_8      = "RWQUO"          ! Pooled quota
$       state_9      = "RWLCK"          ! Lock ID data base
$       state_10     = "RWSWP"          ! Swap file space
$       state_11     = "RWMPE"          ! Modified page list empty
$       state_12     = "RWMPB"          ! Modified page writer busy
$       state_13     = "RWSCS"          ! SCS wait
$       state_14     = "RWCLU"          ! Cluster transition wait
$       state_15     = "RWCAP"          ! CPU capability required
$       state_16     = "RWCSV"          ! Cluster server
$       state_17     = "RWSNP"          ! System snapshot
$       state_18     = "PSXFR"          ! POSIX fork wait
$       state_19     = "RWINS"          ! Inner mode (semaphore) wait
$       state_20     = "RWEXH"          ! 'Exit Handling' wait
$
$       state_last   = 20
$
$       return
$ initialize_variables_end:
$
$
$ write_log: subroutine
$       mail nl: "''p2'" /subject="[check_state] ''p1'"
$       write logfile f$fao("!%D ''p1'", 0)
$ endsubroutine