Getting a Handle on RPG's Open Access | |||||||||||
These are the assorted source files for the Open Access for RPG example published in the July 2010 issue of the iSeries EXTRA newsletter. You can find the article here.. |
|||||||||||
|
The "User" ProgramThis uses the OAR Handler program shown below. Note that the only difference in the code from a conventional write-disk-file is the use of the HANDLER keyword on the file's F-spec. The second parameter to the handler is used to supply the name of the IFS file to use. H dftactgrp(*no) option(*NoDebugIO : *SrcStmt) // IFS output file - file definition specifies fields to output FIFS_OUT1 o e Disk Handler('HND_IFS_J2' : ifs_info1) F UsrOpn FTEST1 if e Disk // Definition of the additional IFS data (path) /copy ifs_cpy D ifs_info1 ds likeds(ifs_hdlr_info_t) /free ifs_info1.path = '/Partner400/IFS_J2_1.csv'; open IFS_OUT1; read TEST1; dow not %eof(TEST1); Write IFS_OUT1R; // read next record read TEST1; enddo; *inlr = *On; The Handler ProgramAll of the real work takes place in this handler. In this example it has been compiled as a PGM object. The /COPY members used (other than the IBM supplied ones) can be found here. // Maximum length of IFS records is 32740 chars // Records will be terminated by the windows-style CR/LF sequence // Character fields are enclosed within double quotes (") // and trailing blanks are removed // Numeric and date fields are output as-is. H DftActGrp(*No) Option(*SrcStmt) // Standard IBM supplied Open Access definitions /copy qrnopenacc // Definition of additional handler parameter and constants /copy ifs_cpy // Standard IBM supplied IFS prototypes /copy qsysinc/qrpglesrc,ifs // RPG Status code values /copy monstatcds // On V7 and later systems this PR can be removed and so can those for // local subprocedures openFile(), writeFile() and closeFile(). D HND_IFS_J2 Pr ExtPgm('HND_IFS_J2') D info likeds(QrnOpenAccess_T) // Definitions for local subprocedures D openFile pr like(fileHandle) D path like(ifs_hdlr_info_t.path) D const D writeFile pr like(filehandle) D handle like(fileHandle) value D closeFile pr D handle like(fileHandle) value D HND_IFS_J2 PI D info likeds(QrnOpenAccess_T) // Field Names/Values structures D nvInput ds likeds(QrnNamesValues_T) D based(pNvInput) // Structure to map the "additional informatin" parameter passed // by the RPG program. In this case it contains the IFS file name. // Its pointer is contained within the userArea field in the info struct D ifs_info ds likeds(ifs_hdlr_info_t) D based(pIfs_info) // Used by the IFS routines to determine which IFS file is to be used // Maps to storage dynamically allocated when opening the file. // Pointer is stored in the rpgStatus field in the info structure D fileHandle s 10i 0 based(pfileHandle) /free // Use the pointers in the info area to set up access to the // the handle for the IFS file (stateInfo) // and the IFS file name (userArea) pfileHandle = info.stateInfo; pIfs_info = info.userArea; If info.rpgOperation = QrnOperation_WRITE; // Set up access to Name/Value information pNvInput = info.namesValues; // Write error is unlikely but signal it if it occurs If ( writeFile(fileHandle) = fileError ); info.rpgStatus = errIO; EndIf; elseIf info.rpgOperation = QrnOperation_OPEN; // Specify that we want to use Name/Value information info.useNamesValues = *On; // Allocate the storage for the file handle and store the pointer // in the info area. That way RPG can associate the pointer with // the specific file and give it back to us on each operation. pfileHandle = %Alloc(%Size(fileHandle)); info.stateInfo = pfileHandle; // Ensure that file handle is zero before attempting open() clear fileHandle; fileHandle = openFile (ifs_info.path); // Open file if fileHandle = fileNotOpen; info.rpgStatus = errImpOpenClose; // Open failed EndIf; elseif info.rpgOperation = QrnOperation_CLOSE; closeFile (fileHandle); // free the state information and null out the info pointer dealloc(n) pfileHandle; info.stateInfo = *null; else; // Any other operation is unsupported so notify RPG info.rpgStatus = 1299; // general error status endif; Return; /end-free P openFile b D openFile pi like(fileHandle) D path like(ifs_hdlr_info_t.path) D const /free return open( path : O_CREAT + O_WRONLY + O_CCSID + O_TRUNC + O_TEXTDATA + O_TEXT_CREAT : S_IRUSR + S_IWUSR + S_IRGRP + S_IROTH : 819 : 0 ); /end-free P openFile e P closeFile b D closeFile pi D handle like(fileHandle) value D rc s 10i 0 /free rc = close (handle); /end-free P closeFile e P writeFile b D pi like(filehandle) D handle like(fileHandle) value D buffer s 32740a Varying Inz D value s 32470a Based(pvalue) D i s 5i 0 D reply s 10i 0 D comma c ',' D quote c '"' D CRLF c x'0d25' /free // Process all fields in record For i = 1 to nvInput.num; pvalue = nvInput.field(i).value; // set up to access data If ( nvInput.field(i).dataType = QrnDatatype_Alpha ) Or ( nvInput.field(i).dataType = QrnDatatype_AlphaVarying); buffer += quote + %trimR( %subst( value: 1: nvInput.field(i).valueLenBytes )) + quote; ElseIf ( nvInput.field(i).dataType = QrnDatatype_Decimal ); buffer += %subst(value: 1: nvInput.field(i).valueLenBytes); ElseIf ( nvInput.field(i).dataType = QrnDatatype_Date ); buffer += %subst(value: 1: nvInput.field(i).valueLenBytes); EndIf; If i <> nvInput.num; // Add comma after every field except the last buffer += comma; EndIf; EndFor; buffer += CRLF; // Add record termination // reply will contain the length of data written or -1 in case of error reply = write ( handle: %Addr(buffer:*Data): %Len(buffer) ); Return reply; /end-free P writeFile e /COPY Files UsedThese are the two /Copy members used. The first is used to describe the additional parameter passed to the handler, in this case to supply the IFS file name. The second is a standard one I use in many programs. It contains the status codes that I normally use with MONITOR. In this case they are used to signal a specific error condition back to the "User" program. The other /COPY members used are IBM supplied. File IFS_CPY// COPY file defining the additional HANDLER parameter used to allow // the RPG program to pass the IFS path to the handler // Also contains constants used in the I/O routines /if defined(IFS_CPY_COPIED) /eof /endif /define IFS_CPY_COPIED D ifs_hdlr_info_t... D ds qualified template D path 5000a varying D fileNotOpen c -1 D fileError c -1 File MONSTATCDS// RPG IV Status codes for use with MONITOR or whatever ... /if defined(MONSTATCDS_COPIED) /eof /endif /define MONSTATCDS_COPIED // 00000 No error. D stsNoError C 00000 // 00001 Called program returned with *INLR on. D stsPgmRetLR C 00001 // 00002 Function key pressed. D stsFkeyPressed C 00002 // 00011 End of file (%EOF = *ON). D stsEOF C 00011 // 00012 Record not found (%FOUND = *OFF). D stsNotFnd C 00012 // 00013 Write to full subfile. D stsWrtSflFull C 00013 // 00050 Conversion resulted in substitution. D stsCvtSubst C 00050 // 00100 String operation, value out of range. D errInvalString C 00100 // 00101 Negative square root. D errNegSqrt C 00101 // 00102 Divide by zero. D errDivZero C 00102 // 00103 Intermediate result too small to contain result. D errResultTooSmall... D C 00103 // 00104 Float underflow. Intermediate value too small. D errFltUndflow C 00104 // 00105 Invalid characters in character to numeric conversion D errInNumConv C 00105 // 00112 Invalid date, time, or timestamp value. D errInvalDate C 00112 // 00113 Date overflow or underflow. D errDateOvflow C 00113 // 00114 Date mapping error. D errDateMap C 00114 // 00115 Invalid length for variable-length field. D errInvalVarLen C 00115 // 00120 Table or array out of sequence. D errArrSeq C 00120 // 00121 Invalid array index. D errArrIdx C 00121 // 00122 OCCUR value out of range. D errInvalOccur C 00122 // 00123 RESET attempted during initialization. D errInzReset C 00123 // 00202 Call to program or procedure ended in error. D errCallFail C 00202 // 00211 Error occurred while calling program or procedure. D errCall C 00211 // 00221 Called program tried to use unpassed parameter. D errParmNoPass C 00221 // 00222 Pointer or parameter error. D errPtrParm C 00222 // 00231 Called program returned with halt indicator on. D errCallHalt C 00231 // 00232 Halt indicator on in this program. D errHalt C 00232 // 00233 Halt indicator on when RETURN operation run. D errHaltRtn C 00233 // 00299 RPG dump failed. D errDumpFail C 00299 // 00301 Error in method call. D errMthCall C 00301 // 00302 Error converting Java array to RPG parm entering Java // native meth D errCvtJavArrEnt... D C 00302 // 00303 Error converting RPG parm to Java array exiting RPG // native method D errCvtRpgPrmOut... D C 00303 // 00304 Error converting RPG parm to Java array preparing // Java meth call. D errCvtRPGtoJavaArray... D C 00304 // 00305 Error cvting Java array to RPG parm/return value // after meth call. D errCvtJavArrayToRPG... D C 00305 // 00306 Error converting RPG return value to Java array. D errcvtRpgRtnVal... D C 00306 // 00333 Error on DSPLY operation. D errDsply C 00333 // 00401 Data area not found. D errDataAreaNotFnd... D C 00401 // 00402 *PDA not valid for non-prestart job. D errInvalPsjPDA C 00402 // 00411 Data area types/lengths do not match. D errInvalDataArea... D C 00411 // 00412 Data area not allocated for output. D errDataAreaNoOutput... D C 00412 // 00413 I/O error while processing data area. D errDataAreaIO... D C 00413 // 00414 Not authorized to use data area. D errDataAreaUseAut... D C 00414 // 00415 Not authorized to change data area. D errDataAreaChgAut... D C 00415 // 00421 Error while unlocking data area. D errDataAreaUnlFail... D C 00421 // 00425 Requested storage allocation length out of range. D errInvalAlloc C 00425 // 00426 Error during storage management operation. D errStorFail C 00426 // 00431 Data area previously allocated to another process. D errDataAreaAlloc... D C 00431 // 00432 *LOCK for data area not granted. D errDataAreaLock... D C 00432 // 00450 Character field not enclosed by SO and SI. D errInvalSosi C 00450 // 00451 Cannot convert between two CCSIDs. D errCvtCcsid C 00451 // 00501 Sort sequence not retrieved. D errSortRtv C 00501 // 00502 Sort sequence not converted. D errSortCvt C 00502 // 00802 Commitment control not active. D errCmtNact C 00802 // 00803 Rollback failed. D errRolbkFail C 00803 // 00804 COMMIT error. D errCmt C 00804 // 00805 ROLBK error. D errRolbk C 00805 // 00907 Decimal data error. D errDecimal C 00907 // 00970 Compiler/runtime level check. D errCompLevChk C 00970 // 01011 Undefined record type. D errUndefRecTyp C 01011 // 01021 Record already exists. D errRecExists C 01021 // 01022 Referential constraint error. D errRefCst C 01022 // 01023 Trigger program error before operation. D errTrgBefore C 01023 // 01024 Trigger program error after operation. D errTrgAfter C 01024 // 01031 Match field sequence error. D errMatchSeq C 01031 // 01041 Array/table load sequence error. D errLoadArr C 01041 // 01042 Array/table load sequence error. D errArrAltSeq C 01042 // 01051 Excess entries in array/table file. D errArrOvflow C 01051 // 01071 Record out of sequence. D errInvalRecSeq C 01071 // 01121 No Print Key DDS keyword indicator. D errDDSPrtKey C 01121 // 01122 No Page Down Key DDS keyword indicator. D errDDSPgDn C 01122 // 01123 No Page Up Key DDS keyword indicator. D errDDSPgUp C 01123 // 01124 No Clear Key keyword indicator. D errDDSClrKey C 01124 // 01125 No Help Key DDS keyword indicator. D errDDSHlpKey C 01125 // 01126 No Home Key DDS keyword indicator. D errDDSHomeKey C 01126 // 01201 Record mismatch detected on input. D errInpMisMatch C 01201 // 01211 I/O operation to a closed file. D errIOClosed C 01211 // 01215 OPEN issued to already open file. D errAlreadyOpen C 01215 // 01216 Error on implicit OPEN/CLOSE. D errImpOpenClose... D C 01216 // 01217 Error on explicit OPEN/CLOSE. D errExpOpenClose... D C 01217 // 01218 Unable to allocate record. D errRcdLocked C 01218 // 01221 Update/delete operation without a prior read. D errUpdNoRead C 01221 // 01222 Referential constraint allocation error. D errRefCstAlloc C 01222 // 01231 Error on SPECIAL file. D errSpecial C 01231 // 01235 Error in PRTCTL space or skip entries. D errPrtCtl C 01235 // 01241 Record number not found. D errRecNbrNotFnd... D C 01241 // 01251 Permanent I/O error. D errPermIO C 01251 // 01255 Session or device error. D errSessDev C 01255 // 01261 Attempt to exceed maximum number of devices. D errMaxDev C 01261 // 01271 Attempt to acquire unavailable device. D errDevUnavail C 01271 // 01281 Operation to unacquired device. D errDevUnacq C 01281 // 01282 Job ending with controlled option. D errJobEndCtl C 01282 // 01284 Unable to acquire second device. D errAcqAddDev C 01284 // 01285 Attempt to acquire an allocated device. D errDevAlloc C 01285 // 01286 Attempt to open shared file with SAVDS or SAVIND. D errShrOpn C 01286 // 01287 Response indicators overlap SAVIND indicators. D errRespInd C 01287 // 01299 I/O error detected. D errIO C 01299 // 01331 Wait time exceeded for WORKSTN file. D errWait C 01331 // 09998 Internal failure in RPG runtime D errIntRPGFail C 09998 // 09999 Program exception in system routine. D errPgmExc C 09999 |
||||||||||
Return to Home Page |
Want more information? |