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.