7.3. Retrieving the internal job id

The takedescriptor() and getdescriptor() APIs require that you know the internal job ID of the job that you wish to pass a descriptor to. This topic discusses the QUSRJOBI (Retrieve Job Information) API which we will use to determine the Internal Job Identifier.

The QUSRJOBI API is an 'Work Management API' (most of the other APIs we've worked with have been 'Unix-Type APIs', which makes it somewhat different.

The IBM manual page for QUSRJOBI is located here: http://publib.boulder.ibm.com/pubs/html/as400/v4r5/ic2924/info/apis/qusrjobi.htm

The prototype listed on this page isn't in C format, but rather is in a somewhat 'language-neutral' format. It looks like this:

Parm# Description Usage Data Type
1 Receiver variable Output Char (*)
2 Length of receiver variable Input Binary (4)
3 Format name Input Char (8)
4 Qualified job name Input Char (26)
5 Internal job identifier Input Char (16)
Optional parameter:
6 Error code I/O Char (*)

QUSRJOBI is actually a program on the system that we need to call (as opposed to a procedure in a service program) The 2nd column of the parameter group listing above tells us whether the parameter is used for "Output" from the API, "Input" to the API, or "I/O" for both input and output.

The Last column explains the data type of the variable used, and that data type's length. A (*) under length indicates that the length can vary, otherwise, the length is the number of bytes to pass.

Since this is a "common gotcha" for people who are calling APIs, I'll say it again. The length is the number of bytes to pass . When it says "Binary(4)", this is NOT the RPG '4B 0' data type. In RPG, '4B 0' means a 4 digit binary number. But, a 4-digit binary number is only 2 bytes long! Instead, a '9B 0' should be passed, or much better yet, a '10I 0' should be passed. In general, the RPG 'I' data type works better for anything called 'binary' than the legacy 'B' data type.

So, the prototype for the QUSRJOBI API will look like this:

         D RtvJobInf       PR                  ExtPgm('QUSRJOBI')
         D   RcvVar                   32766A   options(*varsize)
         D   RcvVarLen                   10I 0 CONST
         D   Format                       8A   CONST
         D   JobName                     26A   CONST
         D   IntJobID                    16A   CONST
         D   ErrorCode                32766A   options(*varsize)
     

Note: Each parameter that's to be 'Input' only to the API is marked as 'CONST'. This is always a good idea, as it protects your program from accidental changes, helps to document the usage of the API, and allows you to substitute expressions for the parameters.

The parameters that can vary in size we used the "options(*varsize)" keyword with. This allows us to call the API using different sized variables for each call.

You'll note that QUSRJOBI return's all of it's data in the 'RcvVar' parm, so we need an idea of what format the data will be in. In fact, most APIs can return data in more than one format, and this format is determined by the 'FORMAT' parameter.

Reading more of the IBM manual page tells us that there are many different formats. Since we only need one that returns the internal job id, we can use any of the formats that it allows. The shortest, and best performing format is called 'JOBI0100', so why don't we use that?

The manual tells us that the format of the returned data for QUSRJOBI looks like this:

Offset    
Dec Hex Type Field
0 0 BINARY(4) Number of bytes returned
4 4 BINARY(4) Number of bytes available
8 8 CHAR(10) Job name
18 12 CHAR(10) User name
28 1C CHAR(6) Job number
34 22 CHAR(16) Internal job identifier
50 32 CHAR(10) Job status
60 3C CHAR(1) Job type
61 3D CHAR(1) Job subtype
62 3E CHAR(2) Reserved
64 40 BINARY(4) Run priority
68 44 BINARY(4) Time slice
72 48 BINARY(4) Default wait
76 4C CHAR(10) Purge

So, we'll make a data structure to use as our receiver variable. That'll help us by separating all of the fields listed above when we get our returned data from the API.

Here's what this data structure should look like:

         D dsJobI0100      DS
         D   JobI_ByteRtn                10I 0
         D   JobI_ByteAvl                10I 0
         D   JobI_JobName                10A
         D   JobI_UserID                 10A
         D   JobI_JobNbr                  6A
         D   JobI_IntJob                 16A
         D   JobI_Status                 10A
         D   JobI_Type                    1A
         D   JobI_SbType                  1A
         D   JobI_Reserv1                 2A
         D   JobI_RunPty                 10I 0
         D   JobI_TimeSlc                10I 0
         D   JobI_DftWait                10I 0
         D   JobI_Purge                  10A
     

And, finally, the 'Error Code' data structure. This is used in a lot of different APIs, and is a convienient way to get returned error info.

It looks like this:

         D dsEC            DS
         D  dsECBytesP             1      4I 0 INZ(256)
         D  dsECBytesA             5      8I 0 INZ(0)
         D  dsECMsgID              9     15
         D  dsECReserv            16     16
         D  dsECMsgDta            17    256
     

Since this prototype & data struct definition don't (directly) have anything to do with sockets, I decided to make a new header file for this API, called 'JOBINFO_H'

If you want to download my copy of JOBINFO_H, you can get it here: http://www.scottklement.com/rpg/socktut/qrpglesrc.jobinfo_h

You call the QUSRJOBI API like this:

         C                   callp     RtvJobInf(dsJOBI0100: %size(dsJOBI0100): 
         C                               'JOBI0100': '*': *BLANKS: dsEC)
         c                   if        dsECBytesA > 0
         C** Error occurred.   Error message number is in dsECMsgID
         C                   endif