The RPG converter will not only convert your code to Java or C#, it can also help improving its structure. In this example, we are going to see how to remove useless intermediate files. This will improve maintainability and performance of the code.
Intermediate files are a common pattern in RPG programming. They show up in CL script as files that are created before a program run and removed right after:
CRTPF FILE(QTEMP/TMPA) ... CALL PGM(PGM001) CALL PGM(PGM002) DLTF FILE(QTEMP/TMPA)
The intermediate file is used as output by one program and as input by another program. Here is the first program:
H* PROGRAM PGM001 ... C* Open intermediate file as output FTMPA O E K DISK ... some loops ... C* Write data to intermediate file C WRITE TMPA
And here is the second program:
H* PROGRAM PGM002 ... C* Open intermediate file as input FTMPA IF E K DISK ... C* Read data from intermediate file C READ TMPA 90 C *IN90 DOWEQ '0' ... do something with the data ...
The default conversion strategy maps an RPG File Specification to an instance of the Java interface File, and attaches file instances to actual files on the system. Here the system file TMPA is still used as an intermediate file:
// PGM001.java // This attaches tmpa to a system file and opens it for input File tmpa = new SystemFile("TMPA", "I"); ... void pgm001() { ... some loops ... { // Write data to intermediate file tmpa.write(); } }
// PGM002.java // This attaches tmpa to a system file and opens it for output File tmpa = new SystemFile("TMPA", "O"); ... void pgm002() { in90 = tmpa.read(); while(in90 == false) { ... do something with the data ... in90 = tmpa.read(); }
(By the way, we will see in an upcoming example how the RPG converter can make this loop much more Java-like).
So far so good, our Java program works as expected. But do we really need to store data to the file system and re-read it immediately after? Modern servers can hold most workloads in memory. This makes programs orders of magnitude faster, and avoids an entire category of problems related to file processing.
What we can do here is to use a different implementation of the File interface, that reads and write to an in-memory buffer.
We must also pass this File instance as a parameter to pgm001() and pgm002(), since they must work on the same in-memory buffer. This transformation must be made manually, as it is not (yet?) supported by the RPG converter. This is what it looks like:
// This attaches tmpa to an in-memory buffer File tmpa = new MemoryFile("TMPA", "IO"); ... void main() { // Now run both programs with the same in-memory buffer // This removes the need for an intermediate file pgm001(tmpa); pgm002(tmpa); }
If memory size is an issue, another possible program architecture is to use two threads communicating via a fixed-size buffer such as java.util.concurrent.ArrayBlockingQueue. At any point in time, there will never be more than a fixed number of element in the buffer between the two programs. This limits memory usage and makes the entire application more responsive.
// This attaches tmpa to an in-memory synchronized buffer File tmpa = new SynchronizedBufferFile("TMPA", "IO"); ... void main() { // Create a thread for each program. // They will communicate and synchronize through tmpa Thread t1 = new Thread(() -> pgm001(tmpa)); Thread t2 = new Thread(() -> pgm002(tmpa)); // Start both threads in parallel t1.start(); t2.start(); // Wait for both threads to terminate t1.join(); t2.join(); }
Et voilà! You’re doing parallel programming with your RPG programs!