API QREXQ
Pulling and Pushing to the REXX Queue
A REXX queue is similar to a data queue, except that a REXX queue is associated with a job, not job independent. Using the QREXQ API a developer can store information for use at any time during the job process. The REXX external data queue provides a way to temporarily hold data which REXX, and any application programs with the proper interface, can use. The data on the queue is accessible by and visible to a user job as lines or as buffers. A buffer is a sub-grouping of lines within a queue, and lines are character strings of arbitrary lengths. Each line can contain up to 32,767 characters. Pulling and entry from the queue is simple. Just set the function to 'P' (pull from queue). If the return code (rCode) is zero, an entry was pulled from the queue.
Pulling Data from the REXX Queue
This is example is an illustration of using the REXX Queue. In this instance, the REXX queue has been loaded by a previous program on the invocation stack. This program reads the queue for the file list that was loaded into the queue.
ctl-Opt DEBUG(*YES) OPTION(*SRCSTMT : *NODEBUGIO) DFTACTGRP(*NO) ACTGRP('CSGXMT') Main(CSG020RP) EXTBININT(*YES) BNDDIR('QC2LE') ; **************************************************************** * PROGRAM NAME - CSG020RP * * * * FUNCTION - Read IFS entries from REXXQ * * * * PROGRAMMER - Steve Croy 06/21/17 * **************************************************************** **************************************************************** * MODIFICATION LOG * * * * DATE PROGRAMMER DESCRIPTION * * * **************************************************************** *------------------------------------------------------------------- * Procedure prototypes *-------------------------------------------------------------------- Dcl-PR PullFromQueue EXTPGM('QREXQ') ; FUNT char(1) ; BUF char(200) ; BUFLEN int(10) ; FLAG int(5) ; RCODE int(5) ; End-PR ; *-------------------------------------------------------------------- * Data Structures *-------------------------------------------------------------------- Dcl-DS BFLDS ; BUFLEN int(10) ; FLAG int(5) ; RCODE int(5) ; End-DS ; *--------------------------------------------------------------------- * Global Variables *--------------------------------------------------------------------- Dcl-S BUF char(200) ; Dcl-S FUNT char(1) ; Dcl-Proc CSG020RP ; Dcl-PI CSG020RP extPgm('CSG020RP') ; p$Path char(200) ; END-PI ; //*------------------------------------------------------------------ //* Pull from REXX Queue //*------------------------------------------------------------------ p$path = *blank ; Clear BFLDS ; buf = *blank ; funt = 'P' ; buflen = 256 ; PullFromQueue ( funt : buf : buflen : flag : rCode ) ; // Get Queue IF rCode = 0 ; // No error p$path = %trim(buf) ; // File name ELSE ; // Else signal p$path = '*****' ; // End of list ENDIF ; RETURN ; End-Proc CSG020RP ;
Loading Data to the REXX Queue
Here is the code that loaded the information to the REXX queue in the first place. The program reads a directory, and the name of each file in the directory will be pushed to the queue with the QREXQ API. It is a simple and fast method of passing a subset of data from one program to another, without writing and reading a database file.
ctl-Opt DEBUG(*YES) OPTION(*SRCSTMT : *NODEBUGIO) DFTACTGRP(*NO) ACTGRP('CSGXMT') Main(CSG010RP) EXTBININT(*YES) BNDDIR('QC2LE') ; **************************************************************** * PROGRAM NAME - CSG010RP * * * * FUNCTION - Read IFS folder and push to REXQ * * * * PROGRAMMER - Steve Croy 06/21/17 * **************************************************************** *------------------------------------------------------------------- * Procedure prototypes *-------------------------------------------------------------------- Dcl-PR PushToQueue EXTPGM('QREXQ') ; FUNT char(1) ; BUF char(200) ; BUFLEN int(10) ; FLAG int(5) ; RCODE int(5) ; End-PR ; Dcl-PR opendir pointer EXTPROC('opendir') ; dirname pointer VALUE ; End-PR ; Dcl-PR closedir int(10) EXTPROC('closedir') ; dirname pointer VALUE ; End-PR ; Dcl-PR readdir pointer EXTPROC('readdir') ; dirp pointer VALUE ; End-PR ; Dcl-PR stat int(10) EXTPROC('stat') ; // Retrieve status information dirp pointer VALUE ; buffer pointer VALUE ; End-PR ; Dcl-PR chdir int(10) EXTPROC('chdir') ; // Change current directory dirp pointer Value ; End-PR ; Dcl-PR strerror pointer EXTPROC('strerror') ; // Retrieve run error message errnum int(10) ; End-PR ; *-------------------------------------------------------------------- * Data Structures *-------------------------------------------------------------------- Dcl-DS BFLDS ; BUFLEN int(10) ; FLAG int(5) ; RCODE int(5) ; End-DS ; Dcl-DS dirent based(p_dirent) ALIGN ; d_reserv1 char(16) ; d_fileno_gen uns(10) ; d_fileno uns(10) ; d_reclen uns(10) ; d_reserv3 int(10) ; d_reserv4 char(8) ; d_nlsinfo char(12) ; nls_ccsid int(10) OVERLAY(d_nlsinfo:1) ; nls_cntry char(2) OVERLAY(d_nlsinfo:5) ; nls_lang char(3) OVERLAY(d_nlsinfo:7) ; nls_reserv char(3) OVERLAY(d_nlsinfo:10) ; d_namelen uns(10) ; d_name char(640) ; End-DS dirent ; * Data structure for Stat()... Dcl-DS statds BASED(p_stat) ALIGN ; st_mode uns(10) ; st_ino uns(10) ; st_nlink uns(5) ; st_uid uns(10) ; st_gid uns(10) ; st_size int(10) ; st_atime int(10) ; st_mtime int(10) ; st_ctime int(10) ; st_dev uns(10) ; st_blksize uns(10) ; st_allocsize uns(10) ; st_objtype char(11) ; st_codepage uns(5) ; st_reserved char(62) ; st_ino_gen_i uns(10) ; End-DS statds ; *----------------------------------------------------------------- * Global Constants *----------------------------------------------------------------- Dcl-C decalage const(18000) ; Dcl-C #ROOT '/' ; Dcl-C #UP 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ; Dcl-C #LO 'abcdefghijklmnopqrstuvwxyz' ; *----------------------------------------------------------------- * Global Variables *----------------------------------------------------------------- Dcl-S errno int(10) ; Dcl-S error_p pointer ; Dcl-S errmsg char(80) ; Dcl-s p_dirent pointer ; Dcl-S p_stat pointer ; Dcl-S dh pointer ; Dcl-S p$Path char(256) ; Dcl-S Name char(256) ; Dcl-S rc int(10) ; Dcl-S w$inam char(256) ; Dcl-S w$pos zoned(3:0) ; Dcl-S w$len zoned(3:0) ; Dcl-s w$path LIKE(p$path : +1 ) ; Dcl-s tpath LIKE(p$path : +1 ) ; Dcl-S tFile char(128) ; Dcl-S w$date zoned(8:0) ; Dcl-S C$date Date inz ; Dcl-S M$date Date inz ; Dcl-S x$date Date ; Dcl-S epochv char(26) INZ('1970-01-01-00.00.00.000000') ; Dcl-S BUF char(256) ; Dcl-S FUNT char(1) ; Dcl-S CloseError int(10) ; Dcl-Proc CSG010RP ; Dcl-PI CSG010RP extPgm('CSG010RP') ; pathIN char(200) CONST options(*NOPASS) ; END-PI; //*------------------------------------------------------------------ //* Set the path statement //*------------------------------------------------------------------ If %parms < 1 ; p$path = '/' ; Else ; p$path = pathIn ; ENDIF ; IF p$path = *BLANKS; p$path = '/'; ENDIF; IF %subst(%trim(p$path):1:1) <> '/'; p$path = '/' + %trim(p$path); ENDIF; w$path = p$path; w$len = %len(%trim(p$path)); IF %subst(p$path:w$len:1) <> '/'; p$path = %trim(p$path) + '/'; ENDIF; p_stat = %alloc(512); w$path = %trim(w$path) + x'00'; //*------------------------------------------------------------------ //* Open Specified Directory. If not found exit the program. //* Read Each Directory Entry... //*------------------------------------------------------------------ dh = opendir(%addr(w$path)); IF dh <> *NULL; DOU p_dirent = *NULL; p_dirent = readdir(dh); IF p_dirent <> *NULL; //*------------------------------------------------------------------ //* Push to REXX Queue //*------------------------------------------------------------------ IF d_namelen < 1024; Name = %subst(d_name: 1: d_namelen); IF %trim(name) <> '.' and %trim(name) <> '..' and name <> *blanks ; w$inam = name; //* get object status buf = %trim(p$path) + %trim(Name); tpath = %trim(p$path) + %trim(Name) + x'00'; rc = stat(%addr(tpath):p_stat); funt = 'A'; buflen = 256; flag = 1; rcode = 0; PushToQueue (funt : buf : buflen : flag : rcode ) ; ENDIF; ENDIF; ENDIF; ENDDO; error_p = strerror(errno); errmsg = %str(error_p); ENDIF; CloseError = closedir(dh); RETURN; END-PROC;
The programs, CSG010RP and CSG020RP reference the REXX queue. CSG010RP is used to read the files in a specified directory and push the name of the file onto the REXX queue. CSG020RP will read the entries from the REXXQ and pass the name of the file to a CL program for action on the individual file, i.e. rename, or move the file from the directory.