7.4. Communicating the job information

The QUSRJOBI API can be used to give us the Internal Job ID that the givedescriptor() API requires. But, before we can call the QUSRJOBI API, we need to know the JobName/Userid/JobNbr of the server instance job.

This leads to a problem. If we haven't submitted the job yet, how can we possibly know it's job number? And even after we've submitted it, how do we find out the number?

The easiest way is to submit the server instance job, and then have it look up it's own job information. Once it has that information, it should communicate it back to the listener program, so that givedescriptor() can be called.

The easiest way for the server instance to communicate back to the listener program is by using a data queue.

The data queue API's are described in the Object APIs manual. You can find them online at this URL: http://publib.boulder.ibm.com/pubs/html/as400/v4r5/ic2924/info/apis/obj2.htm

In our situation, we are interested in calling two of these APIs, they are the 'Receive From Data Queue' API, and the 'Send to a Data Queue' API. (QRCVDTAQ an QSNDDTAQ, respectively)

Here are the parameters listed in the manual for the QSNDDTAQ API:

Required Parameter Group:
1 Data queue name Input Char(10)
2 Library name Input Char(10)
3 Length of data Input Packed(5,0)
4 Data Input Char(*)
Optional Parameter Group 1:
5 Length of key data Input Packed(3,0)
6 Key data Input Char(*)
Optional Parameter Group 2:
7 Asynchronous request Input Char(10)

The RPG prototype for QSNDDTAQ looks like this:

         D SndDtaQ         PR                  ExtPgm('QSNDDTAQ')
         D  dtaqname                     10A   const
         D  dtaqlib                      10A   const
         D  dtaqlen                       5P 0 const
         D  data                      32766A   const options(*varsize)
         D  keylen                        3P 0 const options(*nopass)
         D  keydata                   32766A   const options(*varsize: *nopass)
         D  asyncreq                     10A   const options(*nopass)

Here are the parameters listed in the manual for the QRCVDTAQ API:

Required Parameter Group:
1 Data queue name Input Char(10)
2 Library name Input Char(10)
3 Length of data Output Packed(5,0)
4 Data Output Char(*)
5 Wait time Input Packed(5,0)
Optional Parameter Group 1:
6 Key order Input Char(2)
7 Length of key data Input Packed(3,0)
8 Key data I/O Char(*)
9 Length of sender information Input Packed(3,0)
10 Sender information Output Char(*)
Optional Parameter Group 2:
11 Remove message Input Char(10)
12 Size of data receiver Input Packed(5,0)
13 Error code I/O Char(*)

So, an RPG prototype for the QRCVDTAQ API looks like this:

         D RcvDtaQ         PR                  ExtPgm('QRCVDTAQ')
         D   DtaqName                    10A   const
         D   DtaqLib                     10A   const
         D   DtaqLen                      5P 0
         D   Data                     32766A   options(*varsize)
         D   WaitTime                     5P 0 const
         D   KeyOrder                     2A   const options(*nopass)
         D   KeyLen                       3P 0 const options(*nopass)
         D   KeyData                  32766A   options(*varsize: *nopass)
         D   SenderLen                    3P 0 const options(*nopass)
         D   SenderInfo               32766A   options(*varsize: *nopass)
         D   RmvMsg                      10A   const options(*nopass)
         D   RcvVarSize                   5P 0 const options(*nopass)
         D   ErrorCode                32766A   options(*varsize: *nopass)

Each time one of our server instances starts, it will call QUSRJOBI to look up it's internal job ID. It will then send it's internal job ID, along with it's job name, userid, and job number to the data queue by calling QSNDDTAQ like this:

         D dsJobInfo       DS
         D   MsgType               1     10A
         D   JobName              11     20A
         D   JobUser              21     30A
         D   JobNbr               31     36A
         D   InternalID           65     80A
         c                   callp     SndDtaQ('SVREX6DQ': 'SOCKTUT': 80:
         c                                   dsJobInfo)

Note: We're making the data queue length be 80, and including a 'MsgType' field at the start in case we ever want to make this data queue compatible with those used by display files, icf files, etc.

After the Listener program has submitted its next server instance pgm, it will read an entry off of the data queue to find out the job info it needs to call givedescriptor(). It will call the QRCVDTAQ API like this:

         c                   callp     RcvDtaQ('SVREX6DQ': 'SOCKTUT': Len:
         c                               dsJobInfo: 60)
         c                   if        Len < 80
         c*** timeout occurred.
         c                   else
         C*** dsJobInfo is populated
         c                   endif

Please add the prototypes shown in this topic, as well as the 'dsJobInfo' data structure to the JOBINFO_H member that you created earlier in this chapter.

Or, if you prefer, you can download my copy of JOBINFO_H here: http://www.scottklement.com/rpg/socktut/qrpglesrc.jobinfo_h

We will use this JOBINFO_H member for all of our 'job spawning approach' examples.