|
OpenVMS Programming Concepts Manual
4.2.4.2 Requesting Information About Processes That Match One Criterion
You can use SYS$GETJPI with SYS$PROCESS_SCAN to search for processes
that match an item list with one criterion. For example, if you specify
a search for processes owned by one user name, SYS$GETJPI returns only
those processes that match the specified user name.
Example 4-6 demonstrates how to perform a SYS$PROCESS_SCAN search on
the local node to select all processes that are owned by user SMITH.
Example 4-6 Using SYS$GETJPI and
SYS$PROCESS_SCAN to Select Process Information by User Name |
PROGRAM PROCESS_SCAN
IMPLICIT NONE ! Implicit none
INCLUDE '($jpidef) /nolist' ! Definitions for $GETJPI
INCLUDE '($pscandef) /nolist' ! Definitions for $PROCESS_SCAN
INCLUDE '($ssdef) /nolist' ! Definitions for SS$_NAMES
STRUCTURE /JPIITMLST/ ! Structure declaration for
UNION ! $GETJPI item lists
MAP
INTEGER*2 BUFLEN,
2 CODE
INTEGER*4 BUFADR,
2 RETLENADR
END MAP
MAP ! A longword of 0 terminates
INTEGER*4 END_LIST ! an item list
END MAP
END UNION
END STRUCTURE
STRUCTURE /PSCANITMLST/ ! Structure declaration for
UNION ! $PROCESS_SCAN item lists
MAP
INTEGER*2 BUFLEN,
2 CODE
INTEGER*4 BUFADR,
2 ITMFLAGS
END MAP
MAP ! A longword of 0 terminates
INTEGER*4 END_LIST ! an item list
END MAP
END UNION
END STRUCTURE
RECORD /PSCANITMLST/ ! Declare the item list for
2 PSCANLIST(12) ! $PROCESS_SCAN
RECORD /JPIITMLST/ ! Declare the item list for
2 JPILIST(3) ! $GETJPI
INTEGER*4 SYS$GETJPIW, ! System service entry points
2 SYS$PROCESS_SCAN
INTEGER*4 STATUS, ! Status variable
2 CONTEXT, ! Context from $PROCESS_SCAN
2 PID ! PID from $GETJPI
INTEGER*2 IOSB(4) ! I/O Status Block for $GETJPI
CHARACTER*16
2 PRCNAM ! Process name from $GETJPI
INTEGER*2 PRCNAM_LEN ! Process name length
LOGICAL*4 DONE ! Done with data loop
!********************************************
!* Initialize item list for $PROCESS_SCAN *
!********************************************
! Look for processes owned by user SMITH
PSCANLIST(1).BUFLEN = LEN('SMITH')
PSCANLIST(1).CODE = PSCAN$_USERNAME
PSCANLIST(1).BUFADR = %LOC('SMITH')
PSCANLIST(1).ITMFLAGS = 0
PSCANLIST(2).END_LIST = 0
!********************************************
!* End of item list initialization *
!********************************************
STATUS = SYS$PROCESS_SCAN ( ! Set up the scan context
2 CONTEXT,
2 PSCANLIST)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
! Loop calling $GETJPI with the context
DONE = .FALSE.
DO WHILE (.NOT. DONE)
! Initialize $GETJPI item list
JPILIST(1).BUFLEN = 4
JPILIST(1).CODE = JPI$_PID
JPILIST(1).BUFADR = %LOC(PID)
JPILIST(1).RETLENADR = 0
JPILIST(2).BUFLEN = LEN(PRCNAM)
JPILIST(2).CODE = JPI$_PRCNAM
JPILIST(2).BUFADR = %LOC(PRCNAM)
JPILIST(2).RETLENADR = %LOC(PRCNAM_LEN)
JPILIST(3).END_LIST = 0
! Call $GETJPI to get the next SMITH process
STATUS = SYS$GETJPIW (
2 , ! No event flag
2 CONTEXT, ! Process context
2 , ! No process name
2 JPILIST, ! Item list
2 IOSB, ! Always use IOSB with $GETJPI!
2 , ! No AST
2 ) ! No AST arg
! Check the status in both STATUS and the IOSB, if
! STATUS is OK then copy IOSB(1) to STATUS
IF (STATUS) STATUS = IOSB(1)
! If $GETJPI worked, display the process, if done then
! prepare to exit, otherwise signal an error
IF (STATUS) THEN
TYPE 1010, PID, PRCNAM(1:PRCNAM_LEN)
1010 FORMAT (' ',Z8.8,' ',A)
ELSE IF (STATUS .EQ. SS$_NOMOREPROC) THEN
DONE = .TRUE.
ELSE
CALL LIB$SIGNAL(%VAL(STATUS))
END IF
END DO
END
|
4.2.4.3 Requesting Information About Processes That Match Multiple Values for One Criterion
You can use SYS$PROCESS_SCAN to search for processes that match one of
a number of values for a single criterion, such as processes owned by
several specified users.
You must specify each value in a separate item list entry, and connect
the item list entries with the PSCAN$M_OR item-specific flag.
SYS$GETJPI selects each process that matches any of the item values.
For example, to look for processes with user names SMITH, JONES, or
JOHNSON, substitute code such as that shown in Example 4-7 to
initialize the item list in Example 4-6.
Example 4-7 Using SYS$GETJPI and
SYS$PROCESS_SCAN with Multiple Values for One Criterion |
!********************************************
!* Initialize item list for $PROCESS_SCAN *
!********************************************
! Look for users SMITH, JONES and JOHNSON
PSCANLIST(1).BUFLEN = LEN('SMITH')
PSCANLIST(1).CODE = PSCAN$_USERNAME
PSCANLIST(1).BUFADR = %LOC('SMITH')
PSCANLIST(1).ITMFLAGS = PSCAN$M_OR
PSCANLIST(2).BUFLEN = LEN('JONES')
PSCANLIST(2).CODE = PSCAN$_USERNAME
PSCANLIST(2).BUFADR = %LOC('JONES')
PSCANLIST(2).ITMFLAGS = PSCAN$M_OR
PSCANLIST(3).BUFLEN = LEN('JOHNSON')
PSCANLIST(3).CODE = PSCAN$_USERNAME
PSCANLIST(3).BUFADR = %LOC('JOHNSON')
PSCANLIST(3).ITMFLAGS = 0
PSCANLIST(4).END_LIST = 0
!********************************************
!* End of item list initialization *
!********************************************
|
4.2.4.4 Requesting Information About Processes That Match Multiple Criteria
You can use SYS$PROCESS_SCAN to search for processes that match values
for more than one criterion. When multiple criteria are used, a process
must match at least one value for each specified criterion.
Example 4-8 demonstrates how to find any batch process owned by
either SMITH or JONES. The program uses syntax like the following
logical expression to initialize the item list:
((username = "SMITH") OR (username = "JONES"))
AND
(MODE = JPI$K_BATCH)
|
Example 4-8 Selecting Processes That Match
Multiple Criteria |
!********************************************
!* Initialize item list for $PROCESS_SCAN *
!********************************************
! Look for BATCH jobs owned by users SMITH and JONES
PSCANLIST(1).BUFLEN = LEN('SMITH')
PSCANLIST(1).CODE = PSCAN$_USERNAME
PSCANLIST(1).BUFADR = %LOC('SMITH')
PSCANLIST(1).ITMFLAGS = PSCAN$M_OR
PSCANLIST(2).BUFLEN = LEN('JONES')
PSCANLIST(2).CODE = PSCAN$_USERNAME
PSCANLIST(2).BUFADR = %LOC('JONES')
PSCANLIST(2).ITMFLAGS = 0
PSCANLIST(3).BUFLEN = 0
PSCANLIST(3).CODE = PSCAN$_MODE
PSCANLIST(3).BUFADR = JPI$K_BATCH
PSCANLIST(3).ITMFLAGS = 0
PSCANLIST(4).END_LIST = 0
!********************************************
!* End of item list initialization *
!********************************************
|
See the OpenVMS System Services Reference Manual for more information about SYS$PROCESS_SCAN item
codes and flags.
4.2.5 Specifying a Node as Selection Criterion
Several SYS$PROCESS_SCAN item codes do not refer to attributes of a
process, but to the VMScluster node on which the target process
resides. When SYS$PROCESS_SCAN encounters an item code that refers to a
node attribute, it creates an alphabetized list of node names.
SYS$PROCESS_SCAN then directs SYS$GETJPI to compare the selection
criteria against processes on these nodes.
SYS$PROCESS_SCAN ignores a node specification if it is running on a
node that is not part of a VMScluster system. For example, if you
request that SYS$PROCESS_SCAN select all nodes with the hardware model
name VAX 6360, this search returns information about local processes on
a nonclustered system, even if it is a MicroVAX system.
A remote SYS$GETJPI operation currently requires the system to send a
message to the CLUSTER_SERVER process on the remote node. The
CLUSTER_SERVER process then collects the information and returns it to
the requesting node. This has several implications for clusterwide
searches:
- All remote SYS$GETJPI operations are asynchronous and must be
synchronized properly. Many applications that are not correctly
synchronized might seem to work on a single node because some
SYS$GETJPI operations are actually synchronous; however, these
applications fail if they attempt to examine processes on remote nodes.
For more information on how to synchronize SYS$GETJPI operations, see
Chapter 6.
- The CLUSTER_SERVER process is always a current process, because it
is executing on behalf of SYS$GETJPI.
- Attempts by SYS$GETJPI to examine a node do not succeed during a
brief period between the time a node joins the cluster and the time
that the CLUSTER_SERVER process is started. Searches that occur during
this period skip such a node. Searches that specify only such a booting
node fail with a SYS$GETJPI status of SS$_UNREACHABLE.
- SS$_NOMOREPROC is returned after all processes on all specified
nodes have been scanned.
4.2.5.1 Checking All Nodes on the Cluster for Processes
The SYS$PROCESS_SCAN system service can scan the entire cluster for
processes. For example, to scan the cluster for all processes owned by
SMITH, use code like that in Example 4-9 to initialize the item list
to find all processes with a nonzero cluster system identifier (CSID)
and a user name of SMITH.
Example 4-9 Searching the Cluster for Process
Information |
!********************************************
!* Initialize item list for $PROCESS_SCAN *
!********************************************
! Search the cluster for jobs owned by SMITH
PSCANLIST(1).BUFLEN = 0
PSCANLIST(1).CODE = PSCAN$_NODE_CSID
PSCANLIST(1).BUFADR = 0
PSCANLIST(1).ITMFLAGS = PSCAN$M_NEQ
PSCANLIST(2).BUFLEN = LEN('SMITH')
PSCANLIST(2).CODE = PSCAN$_USERNAME
PSCANLIST(2).BUFADR = %LOC('SMITH')
PSCANLIST(2).ITMFLAGS = 0
PSCANLIST(3).END_LIST = 0
!********************************************
!* End of item list initialization *
!********************************************
|
4.2.5.2 Checking Specific Nodes on the Cluster for Processes
You can specify a list of nodes as well. Example 4-10 demonstrates how
to design an item list to search for batch processes on node TIGNES,
VALTHO, or 2ALPES.
Example 4-10 Searching for Process
Information on Specific Nodes in the Cluster |
!********************************************
!* Initialize item list for $PROCESS_SCAN *
!********************************************
! Search for BATCH jobs on nodes TIGNES, VALTHO and 2ALPES
PSCANLIST(1).BUFLEN = LEN('TIGNES')
PSCANLIST(1).CODE = PSCAN$_NODENAME
PSCANLIST(1).BUFADR = %LOC('TIGNES')
PSCANLIST(1).ITMFLAGS = PSCAN$M_OR
PSCANLIST(2).BUFLEN = LEN('VALTHO')
PSCANLIST(2).CODE = PSCAN$_NODENAME
PSCANLIST(2).BUFADR = %LOC('VALTHO')
PSCANLIST(2).ITMFLAGS = PSCAN$M_OR
PSCANLIST(3).BUFLEN = LEN('2ALPES')
PSCANLIST(3).CODE = PSCAN$_NODENAME
PSCANLIST(3).BUFADR = %LOC('2ALPES')
PSCANLIST(3).ITMFLAGS = 0
PSCANLIST(4).BUFLEN = 0
PSCANLIST(4).CODE = PSCAN$_MODE
PSCANLIST(4).BUFADR = JPI$K_BATCH
PSCANLIST(4).ITMFLAGS = 0
PSCANLIST(5).END_LIST = 0
!********************************************
!* End of item list initialization *
!********************************************
|
4.2.5.3 Conducting Multiple Simultaneous Searches with SYS$PROCESS_SCAN
Only one asynchronous remote SYS$GETJPI request per SYS$PROCESS_SCAN
context is permitted at a time. If you issue a second SYS$GETJPI
request using a context before a previous remote request using the same
context has completed, your process stalls in a resource wait until the
previous remote SYS$GETJPI request completes. This stall in the RWAST
state prevents your process from executing in user mode or receiving
user-mode ASTs.
If you want to run remote searches in parallel, create multiple
contexts by calling SYS$PROCESS_SCAN once for each context. For
example, you can design a program that calls SYS$GETSYI in a loop to
find the nodes in the VMScluster system and creates a separate
SYS$PROCESS_SCAN context for each remote node. Each of these separate
contexts can run in parallel. The DCL command SHOW USERS uses this
technique to obtain user information more quickly.
Only requests to remote nodes must wait until the previous search using
the same context has completed. If the SYS$PROCESS_SCAN context
specifies the local node, any number of SYS$GETJPI requests using that
context can be executed in parallel (within the limits implied by the
process quotas for ASTLM and BYTLM).
Note
When you use SYS$GETJPI to reference remote processes, you must
properly synchronize all SYS$GETJPI calls. Before the operating
system's Version 5.2, if you did not follow these synchronization
rules, your programs might have appeared to run correctly. However, if
you attempt to run such improperly synchronized programs using
SYS$GETJPI with SYS$PROCESS_SCAN with a remote process, your program
might attempt to use the data before SYS$GETJPI has returned it.
|
To perform a synchronous search in which the program waits until all
requested information is available, use SYS$GETJPIW with an
iosb argument.
See the OpenVMS System Services Reference Manual for more information about process
identification, SYS$GETJPI, and SYS$PROCESS_SCAN.
4.2.6 Programming with SYS$GETJPI
The following sections describe some important considerations for
programming with SYS$GETJPI.
4.2.6.1 Using Item Lists Correctly
When SYS$GETJPI collects data, it makes multiple passes through the
item list. If the item list is self-modifying---that is, if the
addresses for the output buffers in the item list point back at the
item list---SYS$GETJPI replaces the item list information with the
returned data. Therefore, incorrect data might be read or unexpected
errors might occur when SYS$GETJPI reads the item list again. To
prevent confusing errors, Compaq recommends that you do not use
self-modifying item lists.
The number of passes that SYS$GETJPI needs depends on which item codes
are referenced and the state of the target process. A program that
appears to work normally might fail when a system has processes that
are swapped out of memory, or when a process is on a remote node.
4.2.6.2 Improving Performance by Using Buffered $GETJPI Operations
To request information about a process located on a remote node,
SYS$GETJPI must send a message to the remote node, wait for the
response, and then extract the data from the message received. When you
perform a search on a remote system, the program must repeat this
sequence for each process that SYS$GETJPI locates.
To reduce the overhead of such a remote search, use SYS$PROCESS_SCAN
with the PSCAN$_GETJPI_BUFFER_SIZE item code to specify a buffer size
for SYS$GETJPI. When the buffer size is specified by SYS$PROCESS_SCAN,
SYS$GETJPI packs information for several processes into one buffer and
transmits them in a single message. This reduction in the number of
messages improves performance.
For example, if the SYS$GETJPI item list requests 100 bytes of
information, you might specify a PSCAN$_GETJPI_BUFFER_SIZE of 1000
bytes so that the service can place information for at least 10
processes in each message. (SYS$GETJPI does not send fill data in the
message buffer; therefore, information for more than 10 processes can
be packed into the buffer.)
The SYS$GETJPI buffer must be large enough to hold the data for at
least one process. If the buffer is too small, the error code
SS$_IVBUFLEN is returned from the SYS$GETJPI call.
You do not have to allocate space for the SYS$GETJPI buffer; buffer
space is allocated by SYS$PROCESS_SCAN as part of the search context
that it creates. Because SYS$GETJPI buffering is transparent to the
program that calls SYS$GETJPI, you do not have to modify the loop that
calls SYS$GETJPI.
If you use PSCAN$_GETJPI_BUFFER_SIZE with SYS$PROCESS_SCAN, all calls
to SYS$GETJPI using that context must request the same item code
information. Because SYS$GETJPI collects information for more than one
process at a time within its buffers, you cannot change the item codes
or the lengths of the buffers in the SYS$GETJPI item list between
calls. SYS$GETJPI returns the error SS$_BADPARAM if any item code or
buffer length changes between SYS$GETJPI calls. However, you can change
the buffer addresses in the SYS$GETJPI item list from call to call.
The SYS$GETJPI buffered operation is not used for searching the local
node. When a search specifies both multiple nodes and SYS$GETJPI
buffering, the buffering is used on remote nodes but is ignored on the
local node. Example 4-11 demonstrates how to use a SYS$GETJPI buffer
to improve performance.
Example 4-11 Using a SYS$GETJPI Buffer to
Improve Performance |
!********************************************
!* Initialize item list for $PROCESS_SCAN *
!********************************************
! Search for jobs owned by users SMITH and JONES
! across the cluster with $GETJPI buffering
PSCANLIST(1).BUFLEN = 0
PSCANLIST(1).CODE = PSCAN$_NODE_CSID
PSCANLIST(1).BUFADR = 0
PSCANLIST(1).ITMFLAGS = PSCAN$M_NEQ
PSCANLIST(2).BUFLEN = LEN('SMITH')
PSCANLIST(2).CODE = PSCAN$_USERNAME
PSCANLIST(2).BUFADR = %LOC('SMITH')
PSCANLIST(2).ITMFLAGS = PSCAN$M_OR
PSCANLIST(3).BUFLEN = LEN('JONES')
PSCANLIST(3).CODE = PSCAN$_USERNAME
PSCANLIST(3).BUFADR = %LOC('JONES')
PSCANLIST(3).ITMFLAGS = 0
PSCANLIST(4).BUFLEN = 0
PSCANLIST(4).CODE = PSCAN$_GETJPI_BUFFER_SIZE
PSCANLIST(4).BUFADR = 1000
PSCANLIST(4).ITMFLAGS = 0
PSCANLIST(5).END_LIST = 0
!********************************************
!* End of item list initialization *
!********************************************
|
4.2.6.3 Fulfilling Remote SYS$GETJPI Quota Requirements
A remote SYS$GETJPI request uses system dynamic memory for messages.
System dynamic memory uses the process quota BYTLM. Follow these steps
to determine the number of bytes required by a SYS$GETJPI request:
- Add the following together:
- The size of the SYS$PROCESS_SCAN item list
- The total size of all reference buffers for SYS$PROCESS_SCAN (the
sum of all buffer length fields in the item list)
- The size of the SYS$GETJPI item list
- The size of the SYS$GETJPI buffer
- The size of the calling process RIGHTSLIST
- Approximately 300 bytes for message overhead
- Double this total.
The total is doubled because the messages
consume system dynamic memory on both the sending node and the
receiving node.
This formula for BYTLM quota applies to both buffered and nonbuffered
SYS$GETJPI requests. For buffered requests, use the value specified in
the SYS$PROCESS_SCAN item, PSCAN$_GETJPI_BUFFER_SIZE, as the size of
the buffer. For nonbuffered requests, use the total length of all data
buffers specified in the SYS$GETJPI item list as the size of the buffer.
If the BYTLM quota is insufficient, SYS$GETJPI (not SYS$PROCESS_SCAN)
returns the error SS$_EXBYTLM.
4.2.6.4 Using the SYS$GETJPI Control Flags
The JPI$_GETJPI_CONTROL_FLAGS item code, which is specified in the
SYS$GETJPI item list, provides additional control over SYS$GETJPI.
Therefore, SYS$GETJPI may be unable to retrieve all the data requested
in an item list because JPI$_GETJPI_CONTROL_FLAGS requests that
SYS$GETJPI not perform certain actions that may be necessary to collect
the data. For example, a SYS$GETJPI control flag may instruct the
calling program not to retrieve a process that has been swapped out of
the balance set.
If SYS$GETJPI is unable to retrieve any data item because of the
restrictions imposed by the control flags, it returns the data length
as 0. To verify that SYS$GETJPI received a data item, examine the data
length to be sure that it is not 0. To make this verification possible,
be sure to specify the return length for each item in the SYS$GETJPI
item list when any of the JPI$_GETJPI_CONTROL_FLAGS flags is used.
Unlike other SYS$GETJPI item codes, the JPI$_GETJPI_CONTROL_FLAGS item
is an input item. The item list entry should specify a longword buffer.
The desired control flags should be set in this buffer.
Because the JPI$_GETJPI_CONTROL_FLAGS item code tells SYS$GETJPI how to
interpret the item list, it must be the first entry in the SYS$GETJPI
item list. The error code SS$_BADPARAM is returned if it is not the
first item in the list.
The following are the SYS$GETJPI control flags.
JPI$M_NO_TARGET_INSWAP
When you specify JPI$M_NO_TARGET_INSWAP, SYS$GETJPI does not retrieve a
process that has been swapped out of the balance set. Use
JPI$M_NO_TARGET_INSWAP to avoid the additional load of swapping
processes into a system. For example, use this flag with SHOW SYSTEM to
avoid bringing processes into memory to display their accumulated CPU
time.
If you specify JPI$M_NO_TARGET_INSWAP and request information from a
process that has been swapped out, the following consequences occur:
- Data stored in the virtual address space of the process is not
accessible.
- Data stored in the process header (PHD) may not be accessible.
- Data stored in resident data structures, such as the process
control block (PCB) or the job information block (JIB), is accessible.
You must examine the return length of an item to verify that the item
was retrieved. The information may be located in a different data
structure in another release of the operating system.
JPI$M_NO_TARGET_AST
When you specify JPI$M_NO_TARGET_AST, SYS$GETJPI does not deliver a
kernel-mode AST to the target process. Use JPI$M_NO_TARGET_AST to avoid
executing a target process in order to retrieve information.
If you specify JPI$M_NO_TARGET_AST and cannot deliver an AST to a
target process, the following consequences occur:
- Data stored in the virtual address space of the process is not
accessible.
- Data stored in system data structures, such as the process header
(PHD), the process control block (PCB), or the job information block
(JIB), is accessible.
You must examine the return length of an item to verify that the item
was retrieved. The information may be located in a different data
structure in another release of the operating system.
The use of the flag JPI$M_NO_TARGET_AST also implies that SYS$GETJPI
does not swap in a process, because SYS$GETJPI would only bring a
process into memory to deliver an AST to that process.
JPI$M_IGNORE_TARGET_STATUS
When you specify JPI$M_IGNORE_TARGET_STATUS, SYS$GETJPI attempts to
retrieve as much information as possible, even if the process is
suspended or being deleted. Use JPI$M_IGNORE_TARGET_STATUS to retrieve
all possible information from a process. For example, use this flag
with SHOW SYSTEM to display processes that are suspended, being
deleted, or in miscellaneous wait states.
Example 4-12 demonstrates how to use SYS$GETJPI control flags to avoid
swapping processes during a SYS$GETJPI call.
Example 4-12 Using SYS$GETJPI Control Flags
to Avoid Swapping a Process into the Balance Set |
PROGRAM CONTROL_FLAGS
IMPLICIT NONE ! Implicit none
INCLUDE '($jpidef) /nolist' ! Definitions for $GETJPI
INCLUDE '($pscandef) /nolist' ! Definitions for $PROCESS_SCAN
INCLUDE '($ssdef) /nolist' ! Definitions for SS$_ names
STRUCTURE /JPIITMLST/ ! Structure declaration for
UNION ! $GETJPI item lists
MAP
INTEGER*2 BUFLEN,
2 CODE
INTEGER*4 BUFADR,
2 RETLENADR
END MAP
MAP ! A longword of 0 terminates
INTEGER*4 END_LIST ! an item list
END MAP
END UNION
END STRUCTURE
STRUCTURE /PSCANITMLST/ ! Structure declaration for
UNION ! $PROCESS_SCAN item lists
MAP
INTEGER*2 BUFLEN,
2 CODE
INTEGER*4 BUFADR,
2 ITMFLAGS
END MAP
MAP ! A longword of 0 terminates
INTEGER*4 END_LIST ! an item list
END MAP
END UNION
END STRUCTURE
RECORD /PSCANITMLST/ ! Declare the item list for
2 PSCANLIST(5) ! $PROCESS_SCAN
RECORD /JPIITMLST/ ! Declare the item list for
2 JPILIST(6) ! $GETJPI
INTEGER*4 SYS$GETJPIW, ! System service entry points
2 SYS$PROCESS_SCAN
INTEGER*4 STATUS, ! Status variable
2 CONTEXT, ! Context from $PROCESS_SCAN
2 PID, ! PID from $GETJPI
2 JPIFLAGS ! Flags for $GETJPI
INTEGER*2 IOSB(4) ! I/O Status Block for $GETJPI
CHARACTER*16
2 PRCNAM, ! Process name from $GETJPI
2 NODENAME ! Node name from $GETJPI
INTEGER*2 PRCNAM_LEN, ! Process name length
2 NODENAME_LEN ! Node name length
CHARACTER*80
2 IMAGNAME ! Image name from $GETJPI
INTEGER*2 IMAGNAME_LEN ! Image name length
LOGICAL*4 DONE ! Done with data loop
!********************************************
!* Initialize item list for $PROCESS_SCAN *
!********************************************
! Look for interactive and batch jobs across
! the cluster with $GETJPI buffering
PSCANLIST(1).BUFLEN = 0
PSCANLIST(1).CODE = PSCAN$_NODE_CSID
PSCANLIST(1).BUFADR = 0
PSCANLIST(1).ITMFLAGS = PSCAN$M_NEQ
PSCANLIST(2).BUFLEN = 0
PSCANLIST(2).CODE = PSCAN$_MODE
PSCANLIST(2).BUFADR = JPI$K_INTERACTIVE
PSCANLIST(2).ITMFLAGS = PSCAN$M_OR
PSCANLIST(3).BUFLEN = 0
PSCANLIST(3).CODE = PSCAN$_MODE
PSCANLIST(3).BUFADR = JPI$K_BATCH
PSCANLIST(3).ITMFLAGS = 0
PSCANLIST(4).BUFLEN = 0
PSCANLIST(4).CODE = PSCAN$_GETJPI_BUFFER_SIZE
PSCANLIST(4).BUFADR = 1000
PSCANLIST(4).ITMFLAGS = 0
PSCANLIST(5).END_LIST = 0
!********************************************
!* End of item list initialization *
!********************************************
STATUS = SYS$PROCESS_SCAN ( ! Set up the scan context
2 CONTEXT,
2 PSCANLIST)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
! Initialize $GETJPI item list
JPILIST(1).BUFLEN = 4
JPILIST(1).CODE = IAND ('FFFF'X, JPI$_GETJPI_CONTROL_FLAGS)
JPILIST(1).BUFADR = %LOC(JPIFLAGS)
JPILIST(1).RETLENADR = 0
JPILIST(2).BUFLEN = 4
JPILIST(2).CODE = JPI$_PID
JPILIST(2).BUFADR = %LOC(PID)
JPILIST(2).RETLENADR = 0
JPILIST(3).BUFLEN = LEN(PRCNAM)
JPILIST(3).CODE = JPI$_PRCNAM
JPILIST(3).BUFADR = %LOC(PRCNAM)
JPILIST(3).RETLENADR = %LOC(PRCNAM_LEN)
JPILIST(4).BUFLEN = LEN(IMAGNAME)
JPILIST(4).CODE = JPI$_IMAGNAME
JPILIST(4).BUFADR = %LOC(IMAGNAME)
JPILIST(4).RETLENADR = %LOC(IMAGNAME_LEN)
JPILIST(5).BUFLEN = LEN(NODENAME)
JPILIST(5).CODE = JPI$_NODENAME
JPILIST(5).BUFADR = %LOC(NODENAME)
JPILIST(5).RETLENADR = %LOC(NODENAME_LEN)
JPILIST(6).END_LIST = 0
! Loop calling $GETJPI with the context
DONE = .FALSE.
JPIFLAGS = IOR (JPI$M_NO_TARGET_INSWAP, JPI$M_IGNORE_TARGET_STATUS)
DO WHILE (.NOT. DONE)
! Call $GETJPI to get the next process
STATUS = SYS$GETJPIW (
2 , ! No event flag
2 CONTEXT, ! Process context
2 , ! No process name
2 JPILIST, ! Itemlist
2 IOSB, ! Always use IOSB with $GETJPI!
2 , ! No AST
2 ) ! No AST arg
! Check the status in both STATUS and the IOSB, if
! STATUS is OK then copy IOSB(1) to STATUS
IF (STATUS) STATUS = IOSB(1)
! If $GETJPI worked, display the process, if done then
! prepare to exit, otherwise signal an error
IF (STATUS) THEN
IF (IMAGNAME_LEN .EQ. 0) THEN
TYPE 1010, PID, NODENAME, PRCNAM
ELSE
TYPE 1020, PID, NODENAME, PRCNAM,
2 IMAGNAME(1:IMAGNAME_LEN)
END IF
ELSE IF (STATUS .EQ. SS$_NOMOREPROC) THEN
DONE = .TRUE.
ELSE
CALL LIB$SIGNAL(%VAL(STATUS))
END IF
END DO
1010 FORMAT (' ',Z8.8,' ',A6,':: ',A,' (no image)')
1020 FORMAT (' ',Z8.8,' ',A6,':: ',A,' ',A)
END
|
|