contact image

Data Queues

Data queues are a type of system object (type *DTAQ) that you can create and maintain using OS/400 commands and APIs. They provide a means of fast asynchronous communication between two jobs, or within the same job, because they use less system resources than database files, message queues, or data areas. You can attach a sender ID to each message being placed on a data queue. The sender ID, an attribute of the data queue that is established when the queue is created, contains the qualified job name and current user profile. Also built into data queues is the ability to set the length of time a job will wait for an entry before continuing its processing. A negative wait parameter will tell the job to wait indefinitely for an entry before processing. A wait parameter of 0 to 99999 will tell the job to wait that number of seconds before processing. When reading messages from a data queue, you have the option to peek at the entry, meaning that your application receives the message but leaves it on the queue; or, you can destroy the entry, meaning that your application receives the entry and removes it from the queue. And, as of V5R1, data queue entries can be journaled.

High-level language programs can send data to a data queue using the QSNDDTAQ (send to a data queue) API and receive data using the QRCVDTAQ (receive from a data queue) API, as well as others. Data queues can be read in a first in, first out (FIFO) sequence, or in a last in, first out (LIFO) sequence, or in keyed sequence. Keyed data queues allow the programmer to specify a specific order in which to receive messages on the data queue or to retrieve only data queue messages that meet a criterion. That is, the programmer can receive a data queue message that is equal to (EQ), greater than (GT), greater than or equal to (GE), less than (LT), or less than or equal to (LE) a search key.

RPG - Print entries in DATAQ

Sample from Jamie Flanary posted at 2011-12-09 20:11:24

     FQSYSPRT   O    F  132        PRINTER OFLIND(*INOF)                                            
      //--*STAND ALONE-------------------------------------------                                   
     d ColumnShift     s             10i 0 inz                                                      
     d cSflPag         c                   const(7)                                                 
     d ff              s              5u 0 inz                                                      
     d ForCounter      s             10i 0 inz                                                      
     d Hex40           c                   const(x'40')                                             
     d i_DtaqNameQual  s             20a   inz('FC3TCOP   JAMIELIB')                                
     d ipaddress       s             20                                                             
     d IsHexMode       s               n   inz(*off)                                                
     d ofs             s             10i 0 inz                                                      
     d p1data          s            125                                                             
     d qTrimLen        s             10i 0 inz                                                      
     d Rcvar           S           5000A   Inz                                                      
     d sflDspPag       s             10i 0 inz                                                      
     d Shift           s              5u 0 inz(58)                                                  
     d TempqDS         s            116a   inz                                                      
     d torecNum        s              5u 0 inz                                                      
     d v0200len        s             10i 0 inz                                                      
     d xx              s             10i 0 inz                                                      
     d UserSpaceName   s             20a   inz('DTAQDUMP  QTEMP     ')                              
      //--*DATA STRUCTURES---------------------------------------                                   
      // Move pointer through message entries                                                       
     d ListEntryDS     ds                  qualified based(ListEntryPtr)                            
     d  NextEntry                    10i 0                                                          
     d  Datetime                      8a                                        TOD format          
     d  MessageData                1000a                                        variable text       
      // Program Info                                                                               
     d                SDS                                                                           
     d  @PGM                 001    010                                                             
     d  @PARMS               037    039  0                                                          
     d  @MSGDTA               91    170                                                             
     d  @MSGID               171    174                                                             
     d  @JOB                 244    253                                                             
     d  @USER                254    263                                                             
     d  @JOB#                264    269  0                                                          
     d qmhrdqm         PR                  extpgm('QMHRDQM ')                   Get q Entry         
     db                                    like(qmhrdqmDS)                      Receiver            
     d                                       Options(*varsize)                                      
     d                               10i 0 const                                Length              
     d                                8a   const                                Api Format          
     d                               20a                                        Dtaq and Lib        
     db                                    like(RDQS0200DS) Options(*varsize)   Key Information     
     d                                        const                                                 
     d                               10i 0 const                                Key Info Length     
     d                                8a   const                                Information         
     db                                    like(ApiErrDS) Options(*varsize)     Error Parm          
      // parms for QMHRDQM retrieve dataq entries                                                   
     d qmhrdqmDS       ds                  qualified based(uheadPtr)                                
     d  BytesReturned                10i 0 overlay(qmhrdqmDS:1)                                     
     d  BytesAvail                   10i 0 overlay(qmhrdqmDS:5)                                     
     d  MsgRtnCount                  10i 0 overlay(qmhrdqmDS:9)                                     
     d  MsgAvlCount                  10i 0 overlay(qmhrdqmDS:13)                                    
     d  KeyLenRtn                    10i 0 overlay(qmhrdqmDS:17)                                    
     d  KeyLenAvl                    10i 0 overlay(qmhrdqmDS:21)                                    
     d  MsgTxtRtn                    10i 0 overlay(qmhrdqmDS:25)                                    
     d  MsgTxtAvl                    10i 0 overlay(qmhrdqmDS:29)                                    
     d  EntryLenRtn                  10i 0 overlay(qmhrdqmDS:33)                                    
     d  EntryLenAvl                  10i 0 overlay(qmhrdqmDS:37)                                    
     d  OffsetToEntry                10i 0 overlay(qmhrdqmDS:41)                                    
     d  DtaqLib                      10a   overlay(qmhrdqmDS:45)                                    
      // Message selection info - RDQS0100 nonkeyed queues  RDQS0200 Keyed data queues              
     d rdqs0100DS      ds                  qualified                                                
     d  Selection                     1a   inz('A')                             all                 
     d  Reserved                      3a                                                            
     d  MsgByteRtv                   10i 0 inz   overlay(rdqs0100DS:5)          message bytes to rtv
      // Error return code parm for APIs.                                                           
     d ApiErrDS        ds                  qualified                                                
     d  BytesProvided                10i 0                                                          
     d  BytesReturned                10i 0                                                          
     d  ErrMsgId                      7a                                                            
     d  ReservedSpace                 1a                                                            
     d  MsgReplaceVal               112a                                                            
     d rdqs0200DS      ds                  qualified                                                
     d  Selection                     1a   inz('K')                             Keyed               
     d  KeyOrder                      2a   inz('GE')                                                
     d  MsgByteRtv                   10i 0 inz   overlay(rdqs0200DS:5)          message bytes to rtv
     d  KeyByteRtv                   10i 0 inz   overlay(rdqs0200DS:9)          keys bytes to rtv   
     d  KeyLen                       10i 0 inz   overlay(rdqs0200DS:13)         key length          
     d  Key                         256a         overlay(rdqs0200DS:17)         key value           
     d quscrtus        PR                  extpgm('QUSCRTUS')                                       
     d                               20a                                                            
     d                               10a   const                                                    
     d                               10i 0 const                                                    
     d                                1a   const                                                    
     d                               10a   const                                                    
     d                               50a   const                                                    
     d                               10a   const                                                    
     db                                    like(ApiErrDS)                                           
     d f_Quscrtus      PR              *                                                            
     d                               20a                                                            
     d qusptrus        PR                  extpgm('QUSPTRUS')                                       
     d                               20a                                                            
     d                                 *                                                            
     db                                    like(ApiErrDS)                                           
     d qmhqrdqd        PR                  extpgm('QMHQRDQD')                   Data q Description  
     db                                    like(qmhqrdqdDS)                     Receiver            
     d                               10i 0 const                                Length              
     d                                8a   const                                Api Format          
     dd                              20a                                        Dtaq and Lib        
     d qmhqrdqdDS      ds                  qualified inz                                            
     d  MsgLength                    10i 0 overlay(qmhqrdqdDS:9)                                    
     d  KeyLength                    10i 0 overlay(qmhqrdqdDS:13)                                   
     d  Sequence                      1a   overlay(qmhqrdqdDS:17)                                   
     d  SenderID                      1a   overlay(qmhqrdqdDS:18)                                   
     d  Text                         50a   overlay(qmhqrdqdDS:20)                                   
     d  LocalOrDDM                    1a   overlay(qmhqrdqdDS:70)                                   
     d  EntryCount                   10i 0 overlay(qmhqrdqdDS:73)                                   
     d  MaxOverFlow                  10i 0 overlay(qmhqrdqdDS:77)                                   
     d  DtaqName                     10a   overlay(qmhqrdqdDS:81)                                   
     d  DtaqLib                      10a   overlay(qmhqrdqdDS:91)                                   
     d APIError        ds                  Qualified                                                
     d  BytesP                 1      4I 0 inz(%size(apiError))                                     
     d  BytesA                 5      8I 0 inz(0)                                                   
     d  Messageid              9     15                                                             
     d  Reserved              16     16                                                             
     d  messagedta            17    256                                                             
     d Infds           ds                                                       INFDS data structure
     d Choice                369    369                                                             
     d Currec                378    379I 0                                                          
        except head;                                                                                
       // create user space                                                                         
       callp QUSCRTUS(                                                                              
             'List Objects  ':                                                                      
             '*NO ':                                                                                
       // Get pointer to object list user spaces                                                    
       callp QUSPTRUS(                                                                              
       // Call API to retrieve data queue description.                                              
       callp QMHQRDQD(                                                                              
           exsr ReadMyQ;                                                                            
       *inlr = *on;                                                                                 
       // Call API to retrieve data queue entries                                                   
       // Different type dataqs require a different parm list to the API.                           
       begsr ReadmyQ;                                                                               
 1b    if qmhqrdqdDS.Sequence = 'K';                                                                
          rdqs0200DS.MsgByteRtv = qmhqrdqdDS.MsgLength;                                             
          rdqs0200DS.KeyByteRtv = qmhqrdqdDS.KeyLength;                                             
          rdqs0200DS.KeyLen = qmhqrdqdDS.KeyLength;                                                 
          v0200Len = 16 + qmhqrdqdDS.KeyLength;  //len of info                                      
          callp QMHRDQM(                                                                            
 1x    else;                                                                                        
          // non keyed                                                                              
          rdqs0100DS.MsgByteRtv = qmhqrdqdDS.MsgLength;                                             
          callp QMHRDQM(                                                                            
 1e    endif;                                                                                       
       // Spin through the dataq entries.                                                           
       // Convert API date/time stamp to human-readable.                                            
       // Load to subfile.                                                                          
 1b    if qmhrdqmDS.MsgRtnCount >  0;                                                               
          // Move pointer through message entries                                                   
          ListEntryPtr = uHeadPtr + qmhrdqmDS.OffsetToEntry;                                        
 2b       for ForCounter = 1 to qmhrdqmDS.MsgRtnCount;                                              
             exsr srTempqDS;                                                                        
             //viewqDS = %subst(TempqDS: 1);                                                        
             ListEntryPtr = uHeadPtr + ListEntryDS.NextEntry;                                       
 2e       endfor;                                                                                   
 1e    endif;                                                                                       
       // Fill TempqDS from User Space Data.                                                        
       // Note: If Keyed data queue, then there is an unexplained                                   
       // 5 bytes at the beginning of each key.                                                     
       // not sure if this a bug or an undocumented feature.                                        
       // Also the size of the msg entry could be larger than  msg variable                         
       // allowed. qTrimLen is used to make sure this doesn't blow up!                              
       begsr srTempqDS;                                                                             
       qTrimLen = qmhqrdqdDS.MsgLength - ofs;                                                       
 1b    if qmhqrdqdDS.Sequence = 'K';                                                                
 2b       If (5 + qmhqrdqdDS.KeyLength) + qmhqrdqdDS.MsgLength                                      
             > %size(ListEntryDS.MessageData);                                                      
             qTrimLen =                                                                             
             %size(ListEntryDS.MessageData) - (5 + qmhqrdqdDS.KeyLength);                           
 2e       endif;                                                                                    
          // RMH -Entry/Key display mode.                                                           
             TempqDS =                                                                              
             5 + qmhqrdqdDS.KeyLength + ofs: qTrimLen);                                             
 1x    else;                                                                                        
 2b       if qmhqrdqdDS.MsgLength > %size(ListEntryDS.MessageData);                                 
             qTrimLen = %size(ListEntryDS.MessageData);                                             
 2e       endif;                                                                                    
          // When the actual message                                                                
          // received is shorter than the maximum entry possible                                    
          // TempqDS = %subst(ListEntryDS.MessageData: 1 + ofs: qTrimLen);                          
 2b       if ofs + 1 <= %size(ListEntryDS.MessageData);                                             
             TempqDS = %subst(ListEntryDS.MessageData: 1 + ofs);                                    
 2x       else;                                                                                     
             TempqDS = *blanks;                                                                     
 2e       endif;                                                                                    
          // write records to subfile                                                               
          p1data = %trim(tempqDS);                                                                  
          if *inof = *on;                                                                           
           except head;                                                                             
           *inof = *off;                                                                            
          except detail;                                                                            
 1e    endif;                                                                                       
     OQSYSPRT   E            HEAD           1 03                                                    
     O                                           10 'data'                                          
     O          E            DETAIL         1                                                       
     O                       p1data             130                                                 

RPGLE - Build, Add entries then read.

Sample from Jamie Flanary posted at 2011-12-09 20:06:52

     d TimeStamp       s               Z                                                            
     d IsOdate         s               D                                                            
     d Count           s              4  0                                                          
     d Count2          s              4  0                                                          
     d CmdString       s            256                                                             
     d CmdLength       s             15  5                                                          
     d Reply           s              1                                                             
     d Chr26           s             26                                                             
      * The defined fields for the QRCVDTAQ                                                         
     d   DtaqName      s             10A   inz('TEST')                                              
     d   DtaqLib       s             10A   inz('JAMIELIB')                                          
     d   DtaqLen       s              5P 0 inz(1000)                                                
     d   Data          s             40A                                                            
     d   WaitTime      s              5P 0 inz(-1)                                                  
     d   KeyOrder      s              2A                                                            
     d   KeyLen        s              3P 0                                                          
     d   KeyData       s          32766A                                                            
     d   SenderLen     s              3P 0                                                          
     d   SenderInfo    s          32766A                                                            
     d   RmvMsg        s             10A   inz('*YES')                                              
     d   RcvVarSize    s              5P 0                                                          
     d   ErrorCode     s          32766A                                                            
     d   Receiver      s           2322                                                             
     d   ReceiverLen   s              4B 0 inz(2322)                                                
     d   ReceiverFmt   s              8    inz('RDQM0100')                                          
     d   DataQName     s             20    inz('TEST      JAMIELIB')                                
     d   MessageSel    s            272                                                             
     d   MessageSelLn  s              4B 0 inz(32)                                                  
     d   MessageFmt    s              8    inz('RDQS0200')                                          
     d   Error         s              4B 0 inz(0)                                                   
      * constants                                                                                   
     d Q               c                   const('''')                                              
     ** Delete the message queue                                                                    
     c                   eval      cmdstring = 'DLTDTAQ JAMIELIB/TEST'                              
     c                   eval      cmdlength = %len(%trim(cmdstring))                               
     c                   call(e)   'QCMDEXC'                                                        
     c                   parm                    cmdstring                                          
     c                   parm                    cmdlength                                          
     ** CRTDTAQ DTAQ(QTEMP/TEST) MAXLEN(1000) SEQ(*KEYED)                                           
     ** KEYLEN(05) SENDERID(*YES)                                                                   
     c                   eval      cmdstring = 'CRTDTAQ DTAQ(JAMIELIB/TEST) '  +                    
     c                             'MAXLEN(1000) SENDERID(*YES)'              +                     
     c                             ' TEXT(' + Q + 'test dataq'+ Q + ')'                             
     c                   eval      cmdlength = %len(%trim(cmdstring))                               
     c                   call(e)   'QCMDEXC'                                                        
     c                   parm                    cmdstring                                          
     c                   parm                    cmdlength                                          
     ** Clear data queue                                                                            
     c                   call(e)   'QCLRDTAQ'                                                       
     c                   parm                    DtaqName                                           
     c                   parm                    DtaqLib                                            
     c                   for       Count = 1 to 5                                                   
     c                   eval      Data = 'Test entry' + %char(Count) +                             
     c                                     '-' + %char(%time())                                     
     c                   call(e)   'QSNDDTAQ'                                                       
     c                   parm                    DtaqName                     Data queue name       
     c                   parm                    DtaqLib                      Data queue library    
     c                   parm                    DtaqLen                      Data queue length     
     c                   parm                    Data                         Queued data           
     c****>              parm                    KeyLen                       Key length            
     c****>              parm                    KeyData                      Key value             
     c                   endfor                                                                     
     c                   eval      *INLR = *on                                                      

CLP - QMHRDQM API does not remove received messages

Sample from Jamie Flanary posted at 2011-12-09 20:06:33

DCL        VAR(&DATA) TYPE(*CHAR) len(512)                                                          
DCL        VAR(&RCVVAR) TYPE(*CHAR) len(512)                                                        
DCL        VAR(&LENGTH) TYPE(*INT) LEN(4)                                                           
DCL        VAR(&FMTNAME) TYPE(*CHAR) LEN(8) +                                                       
DCL        VAR(&NAME) TYPE(*CHAR) LEN(20)                                                           
DCL        VAR(&MSGINF) TYPE(*CHAR)                                                                 
DCL        VAR(&MSGLEN) TYPE(*INT) LEN(4)                                                           
DCL        VAR(&MSGFMT) TYPE(*CHAR) LEN(8) VALUE(RDQS0100)                                          
DCL        VAR(&ERRCDE) TYPE(*CHAR)                                                                 
             CHGVAR     VAR(&NAME) VALUE('DATAQ     JAMIELIB ')                                     
             CHGVAR     VAR(&LENGTH) VALUE(512)                                                     
             CHGVAR     VAR(&MSGLEN) VALUE(80)                                                      
CALL       PGM(QMHRDQM) PARM(&RCVVAR &LENGTH &FMTNAME +                                             
             chgvar &data &rcvvar