|  | |||||||||||
| 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? |