U bent hier

Use an internal buffer for writing groups of lines to an IFS file in RPGLE

The H-line requires QC2LE, because we will be using C functions...

H bnddir('QC2LE')

Prototypes

As mentioned, some C functions for accessing IFS files, and for copying memory blocks:
Notice that below there is an ifsWrite and an iifsWrite ("Internal-ifsWrite"): ifsWrite is used by the application code lines, while iifsWrite is used by ifsWrite to do the actual writing to the IFS file

D memcpy          PR            10I 0 ExtProc('memcpy')           
D  dest                           *   Value OPTIONS(*STRING)      
D  source                         *   Value OPTIONS(*STRING)      
D  count                        10I 0 Value                       
                                                                  
D ifsOpen         pr              *   ExtProc('_C_IFS_fopen')     
D  pFileName                      *   Value                       
D  pFileMode                      *   Value                       
D iifsWrite       pr              *   ExtProc('_C_IFS_fputs')     
D  pStringAddr                    *   Value                       
D  pFileHandle                    *   Value                       
D ifsClose        pr                  ExtProc('_C_IFS_fclose')    
D  pFileHandle                    *   Value                       
D strerror        PR              *   ExtProc('strerror')         
D    errnum                     10I 0 value                       
D @__errno        PR              *   ExtProc('__errno')          
D ifsWrite        pr                                              
D  pStringAddr                    *   Value                       
D  pFileHandle                    *   Value                       
D  pJournaled                     n   Const Options(*omit:*nopass)

A procedure's prototype ifsFlush; to flush the data to the actual IFS file:

D ifsFlush        pr
D pCommit                         n                               

Usage of the procedures

When the program does DB2 and IFS output, it uses the procedure ifsWrite to 'write' data to an IFS file, the IFS file is previously opened with ifsOpen which returned a handle, gFileHandle:

/Free
 aOutputLine = %Trim(aOutputLine) + x'0D00';
 ifsWrite(%Addr(aOutputLine): gFileHandle);
/End-Free

And when the program decides a commit or a rollback, it can do a flush with the ifsFlush procedure (implementation of this procedure: see below):

/Free
 Commit;
 ifsFlush(true);
/End-Free

or

/Free
 Rolbk;
 ifsFlush(false);
/End-Free

Implementations

P ifsWrite        B                                               
D ifsWrite        pi                                              
D  pStringAddr                    *   Value                       
D  pFileHandle                    *   Value                       
D  pJournaled                     n   Const Options(*omit:*nopass)
D aJournaled      s               n                               
D aNewAlloc       s               *                               
D acrlfScanPos    s               *                               
d aStringcrlf     s              2a   Based(acrlfScanPos)         
D aStringSize     s             10i 0                             
 /Free                                                            
  if (%Parms()>2) and (%Addr(pJournaled)*null);                 
    aJournaled=pJournaled;                                        
  else;                                                           
    aJournaled=true;                                              
  endif;                                                          
  if (aJournaled);                                                
    acrlfScanPos=pStringAddr;                                     
    aStringSize=2;                                                
    monitor;                                                      
      DoW (aStringcrlfx'0D00');                                    
        acrlfScanPos+=1;                                          
        aStringSize+=1;                                           
      EndDo;                                                      
    on-error;                                                           
      syLog('err;*gen;Data journal buffer error. Invoice dropped');     
    endmon;                                                             
    aNewAlloc=%Alloc(%Size(gifsPendingFileBuffer));                     
    if (gifsPendingFileBufferRootPointer=*null);                        
      gifsPendingFileBufferRootPointer=aNewAlloc;                       
    else;                                                               
      gifsPendingFileBuffer.PendingFileBufferNextPointer=aNewAlloc;     
    endif;                                                              
    gifsPendingFileBufferCurrentPointer=aNewAlloc;                      
    gifsPendingFileBuffer.RecordFileHandle=pFileHandle;                 
    gifsPendingFileBuffer.RecordPointer=%Alloc(aStringSize);            
    memcpy(gifsPendingFileBuffer.RecordPointer:pStringAddr:aStringSize);
    gifsPendingFileBuffer.PendingFileBufferNextPointer=*null;           
  else;                                                                 
    iifsWrite(pStringAddr:pFileHandle);                                 
  endif;                                                                
 /End-Free                                                              
P ifsWrite        E                                                     
                                                                        
                                                                        
P ifsFlush        B                                                     
D ifsFlush        pi              
D pCommit                         n                               
d aToDeAlloc      s               *                                     
 /Free                                                                  
  gifsPendingFileBufferCurrentPointer=                                  
     gifsPendingFileBufferRootPointer;                                  
  DoW (gifsPendingFileBufferCurrentPointer*null);                     
    if (pCommit); // flush into endless universe if commit is false
      iifsWrite(gifsPendingFileBuffer.RecordPointer                     
               :gifsPendingFileBuffer.RecordFileHandle);                
    endif;                                                              
    dealloc gifsPendingFileBuffer.RecordPointer;                        
    aToDeAlloc = gifsPendingFileBufferCurrentPointer;                   
    gifsPendingFileBufferCurrentPointer=                                
      gifsPendingFileBuffer.PendingFileBufferNextPointer;               
    dealloc aToDeAlloc;                                                 
  EndDo;                                                                
  gifsPendingFileBufferRootPointer=*null;                               
 /End-Free                                                              
P ifsFlush        E

Pointer structure definitions

You have noticed the pointer variables above. This is the definition of it:

D gifsPendingFileBufferRootPointer...                                      
D                 s               *                                        
D gifsPendingFileBufferCurrentPointer...                                   
D                 s               *                                        
D gifsPendingFileBuffer...                                                 
D                 DS                  Qualified                            
D                                     Based(                               
D                                      gifsPendingFileBufferCurrentPointer)
D   RecordFileHandle...                                                    
D                                 *                                        
D   RecordPointer...                                                       
D                                 *                                        
D   PendingFileBufferNextPointer...                                        
D                                 *                                        

Don't forget to initialize the two global variables before starting to work with them

/Free
  gifsPendingFileBufferRootPointer=*null;   
  gifsPendingFileBufferCurrentPointer=*null;
/End-Free
IT area: