Raincode JCL


Version 6.0.136.0

Raincode Crossbow

Raincode Crossbow is a consistent release of the entire Raincode product line, covering compilers, emulators and ancillary tools.

In practice, Raincode Crossbow is designed with three driving forces:

  • A focus on performance across the board:

    • The internal computation engine for non-binary numeric data types (display numeric or packed decimals) has been entirely overhauled, resulting in performance improvements that can go up to a factor of 5 (depending on the level of dependence on these non-binary data types)

    • The file I/O layer has been optimized to ensure the best possible performance when dealing with indexed or sequential files

    • RadaR is a revolutionary solution to run batch steps 5 to 10 times faster, without changing the application source code or even the JCL they are called from

    • The Visual Studio plugin now runs the heaviest debugging operations asynchronously, thereby dramatically improving response time and the overall user experience, even when debugging programs with hundreds of active variables

    • The views generated to access VSAMSql and IMSql data using plain SQL DML statements have been optimized dramatically

  • Updated .NET platform support running both on Linux and on Windows, on virtual machines or in containers, on the cloud, on laptops or servers managed on premise.

  • Consolidation of the product suite, allowing all Raincode software to be built and upgraded synchronously, thereby avoiding the headaches that come from multiple products that follow different (and sometimes, incompatible) release cycles.

Version 6.0

In addition to the above description, Raincode Crossbow v6.0 (see release notes) is a technical release that includes the following:

  • Support for .NET 10.0 and SQL Server 2025 across the board.

  • The Visual Studio plugin now supports Visual Studio 2022 and 2026, with improved support for JCL debugging.

  • Support for the File-AID JCL utility.

  • Support for TLS encryption on QIX and IMS TN3270 terminal servers.

  • Removal of support for .NET Framework and .NET 6.0.

  • Removal of support for Microsoft Host Integration Server (HIS) for Db2.

  • Removal of 32-bit support.

1. Introduction

Raincode JCL executes z/OS’s Job Entry Subsystem (JES) mainframe JCLs with the same behavior, so that batch environments can be rehosted without requiring changes to the existing JCLs. It includes:

  • A JCL interpreter, that recognizes all the idiosyncrasies supported by JES on the mainframe

  • A comprehensive set of the most commonly used JCL utilities, that mimic the behavior of their mainframe counterparts

  • More specifically, among these utilities, Raincode JCL includes a high-performance sorting engine that can be used to sort even the largest data files efficiently

  • A comprehensive API to allow for the development of bespoke JCL utilities

  • Sample utilities provided in complete and compilable source form.

On the other hand, Raincode JCL does not include a scheduler. It is designed to be compatible with all third-party schedulers available on the market.

Raincode JCL is also designed to be programmatically customized, extended and integrated. Because of this flexibility through code, the intended audience of this document is twofold:

  • The operations staff, who need to be able to install, configure, operate and troubleshoot Raincode JCL

  • The development team, who want to go the extra mile, and change the behavior of Raincode JCL by means of its numerous programmatic interfaces.

The structure of this document reflects this duality. After this introductory chapter, which is targeted for both operations and development staff, the document is split into two parts. The first part primarily targets operations, describing how to work with the different parts of Raincode JCL. The second part exclusively targets the development team, explaining how to customize and extend Raincode JCL through code.

Readers of the second part should obviously be familiar with the core elements laid out in the first part, as it describes the functionalities that they will be extending and customizing through code.
image004
Figure 1. Overall architecture diagram

As shown in the figure above, Submit.exe is the executable entry point to Raincode JCL. In turn, it relies on a number of components, namely the catalog manager, the parser and the batch runtime; each of which is further divided into multiple smaller modules.

For simplicity, this document will refer to the entry point of Raincode JCL as Submit.exe, even though it will be named Submit.dll when running on Linux, to be started by a command such as dotnet Submit.dll.
The default installation directory for Raincode JCL on Windows, depending on the version, is C:\Program Files\Raincode\JCL\net10.0 or C:\Program Files\Raincode\JCL\net8.0. The environment variable %RCBATCHDIR% points to the directories holding the different executables, including Submit.exe. The location of the catalog, utilities, and logs are configurable (see section Catalog configuration) for more details.

1.1. Submit.exe

Submit.exe is the equivalent of the mainframe’s SUBMIT command, which allows users to submit a JCL for execution. This can be achieved by starting Submit.exe on the command-line, or programmatically by calling the SubmitRunner.Execute() method.

All the coordination with the filesystem, launched processes, the interactions with the catalog, and the entire processing of a JCL is encapsulated in the call to Submit.exe. This design allows horizontal scaling by running jobs from different servers without a central coordinating server. The return code of Submit.exe is the highest return code of all the steps of the job for easy reporting and integration with schedulers. Editing the .NET configuration file for Submit.exe allows for custom configuration of various interfaces that provide extensibility.

For a complete description of the command-line options available for Submit.exe, please refer to Submit. The most straightforward way to execute Raincode JCL is to call Submit.exe by providing the JCL to execute with the -File option:

simple

After execution, the resulting logs are stored in C:\ProgramData\Raincode\Batch\SYSOUT, as shown in the example below:

image010
Figure 2. Logs SYSOUT

1.2. Catalog manager

Raincode JCL’s catalog manager emulates the catalog manager of the mainframe file system. It maintains its configuration information in an XML file, which is found by default in C:\ProgramData\Raincode\Batch\Raincode.Catalog.xml(shown in the figure below).

image008
Figure 3. Raincode JCL catalog location

The default volume location for data sets managed by the catalog manager is C:\ProgramData\Raincode\Batch\DefaultVolume, as illustrated in the figure below.

image009
Figure 4. Default volume

The catalog manager can be accessed programmatically by developers. Internally, it relies on three subsystems, namely the data file manager, the lock manager and the file system support layer.

image003 1
Figure 5. Catalog manager
  • The data file manager handles the correlation for files (datasets) between the program and JCL for each step. Data files are represented by dataset objects, which describe the record layout and other information required for running job steps.

  • The lock manager obtains and releases the necessary locks on datasets when used by JCLs. These locks depend on the SHR option specified on the DD card. When running on Windows, locks are performed using the Win32 API function LockFileEx to lock a portion of the metadata file. This mechanism supports locking across network file shares and coordinates access between simultaneously running jobs.

  • The file system support layer is responsible for performing the physical I/O operations when reading, updating and writing files.

For more information on Raincode’s approach to handling datasets, please refer to Representation of the datasets.

1.3. The parser

The JCL parser is an internal component of Raincode JCL, which is irrelevant to the day-to-day use of the tool, but which can prove very useful for programmatic interaction with the product. This parser takes the JCL and builds an internal representation, that can then be used to process and execute it. The JCL parser includes support for two levels of preprocessing (performed before actually building the internal representation), namely AutoEdit preprocessing and JCL preprocessing.

Parser
Figure 6. Parser

The AutoEdit preprocessing phase partially mimics a functionality provided by Control-M. It includes date processing, where calendar files can be specified in the Control-M format or programmatically through the IAutoEditCalendar interface. Variables can be set externally using an environment variable CTM_xxxx, where xxxx is the AutoEdit variable name.

In the JCL preprocessing phase, %%SET statements and &VARIABLE references are supported, similar to how they are processed on the mainframe.

The JCL parser may be accessed programmatically by developers, to allow for the input JCL stream to be altered at various stages of the processing by using the IJclPreprocessor interface.

1.4. Batch runtime

The batch runtime is responsible for the different steps in executing a JCL. The basic flow of execution involves scanning, executing and cleanup, as illustrated in the figure below.

image007
Figure 7. Batch runtime

The process flows is as follows:

  1. The JCL is scanned once, the intermediate representation is built, and execution is started.

  2. The job execution process goes through the steps one by one, and checks for all the conditions that control their execution.

    1. The step execution process is then responsible for executing one step in a given JCL. If needed, it will use the runner (see rclrun.exe) to run the executable program for that step. Alternatively, for a selected subset of the utilities, Raincode JCL allows for the execution to happen in-process, thereby avoiding the overhead of writing intermediate files, starting a subprocess, etc. and significantly improving performance.

    2. The step cleanup process is executed at the end of each step execution, dealing with matters such as releasing datasets no longer used in the following steps.

  3. Finally, the job cleanup process is executed at the end of each JCL.

When the runtime looks for a program to execute, it looks successively in the paths defined by:

  1. STEPLIB, as defined in the JCL (STEPLIB can be specified for all the steps or for one step only)

  2. JOBLIB, as defined in the JCL (JOBLIB is generally specified for the entire JCL and is defined before the first step)

  3. The default location, defined in the catalog definition.

  4. The current directory where Submit.exe is called from.

Programmatically, the batch runtime consists of an in-memory object model representing a JCL job and classes that facilitate the execution of steps. The parser builds up this in-memory job representation, and the Submit runner calls the Scan() and Execute() methods on the job to direct the process.

The entry point into the Scan/Execution facility is Raincode.Batch.Submit.SubmitRunner, which is contained in the Submit.exe executable. The static Execute() method can be called with options that specify an actual file to parse into a Job object and execute or a pre-built Job object.

1.5. The runner

Programs compiled by Raincode’s COBOL, PL/I, HLASM and zTrieve compilers cannot be executed directly from the command-line. They require a runner, an executable program that sets up the entire environment (memory, I/O, database connection, etc.) before actually executing the program.

The default runner is %RCBIN%\rclrun.exe. In the spirit of flexibility and extensibility, Raincode JCL (and the entire Raincode toolset) allows for the definition and usage of specialized, user-defined runners, to be used instead of the default one. In practice, this means that Submit.exe and the IKJEFT01 utility go through the runner to execute a compiled module, and leverage rclrun.exe to run these DLLs.

By default, the runner will search for the RCDIR environment variable and execute from the given path. If the RCDIR environment variable is not set, it will execute in the current directory.

The default runner can may be overridden in such a way that a user-defined runner is used instead. This is done by successively trying the following steps:

  1. The content of the RC_LegacyRunner environment variable

  2. The content of the LegacyRunner environment variable LegacyRunner

  3. The content of the catalog configuration XML entity legacyRunner

When Submit.exe starts executing a program by means of a runner (the default one or a redefined version of it), the environment variable RC_LegacyRunner is set to the path of the runner that is actually used.

Part I: Operations

2. Mainframe file system emulation

Mainframe datasets are stored in Windows or Linux files. These files are managed by the catalog system, emulating the mainframe file name structure using the DSN and syntax. In the Raincode catalog, a separate directory is created for each qualifier part of the DSN (qualifiers are separated by periods). Because the underlying file system cannot natively treat mainframe dataset attributes such as, e.g. record format and record length, datasets are stored as two files: one with a .meta and one with a .seq extension. The metadata of the dataset will be stored in the file .meta, and the data itself will be stored in .seq.

For example, consider the DSN XXX1.XXX2.FILE1. Inside the directory XXX1, there is a subdirectory XXX2, and the rightmost part of the DSN (FILE1) yields the files FILE1.seq and FILE1.meta in the subdirectory.

In addition to plain datasets, Raincode also provides native support for Partitioned datasets and Generation data group. These are stored as directories, with a special extension (._dir) to distinguish them from other folders.

2.1. File system emulation with an example

An example shows how the Raincode catalog emulates the mainframe file system. Refer to the following structure of datasets on the mainframe (also shown in Figure Datasets on mainframe):

  • RAINCODE.PROJECT1: High-level qualifier.

  • PDSTEST: Partitioned dataset.

  • GDMODEL1: Plain dataset.

  • GDGROUP1: Generation data group dataset.

  • GDGROUP1.G0001V00 and GDGROUP1.G0002V00 are the two files (versions) of the GDG dataset.

    • G0001V00 is version 1.

    • G0002V00 is version 2. (current version)

datasets on mainframe
Figure 8. Datasets on mainframe

On Windows, this yields the following structure (also shown in Figure Datasets on windows):

  • Two qualifiers (Folders):

    • RAINCODE

    • PROJECT1

  • Two directories for PDS and GDG (._dir):

    • GDGROUP1

    • PDSTEST

  • File Dataset:

    • GDMODEL1

datasets on windows
Figure 9. Datasets on windows

2.1.1. Partitioned dataset

A Partitioned Dataset (PDS), contains one or more members. These members are separate from each other. This structure is illustrated in the figure below.

pds on mainframe
Figure 10. PDS on Mainframe layout

In Windows, this gives the following structure: PDSTEST._dir, which contains MEM1 and MEM2, as shown in the figure below.

pds on windows
Figure 11. PDS on Windows layout

2.1.2. Generation data group

A Generation Data Group (GDG), is the versioning of one dataset that is successive generations of historically related data. This structure is illustrated in the figure below.

GDG on mainframe
Figure 12. GDG on mainframe layout

In Windows, this gives a structure where the directory contains the two versions of the GDG: G0001V00 and G0002V00, as shown in the figure below.

GDG on windows
Figure 13. GDG on windows Layout

2.1.3. Metadata

In mainframe, metadata is stored in the catalog, for example, the metadata of RAINCODE.PROJECT1.PDSTEST is illustrated in the figure below.

datasets mainframe
Figure 14. Datasets metadata on Mainframe

The metadata for the same file on windows is as follows:

<dataSet
  name="RAINCODE.PROJECT1.PDSTEST"
  copies="0"
  isCataloged="TRUE"
  createDate="02/11/2020 09:41:47"
  dataSetType="PDS"
  expireDate="12/31/9999 23:59:59"
  fileFormat="EntrySequenced"
  markForDeletion="FALSE"
  recordFormat="FB"
  recordLength="80"
>
<FileConfig></FileConfig>
</dataSet>

2.2. Concatenated Datasets

On a mainframe, a JCL can specify a concatenated dataset; multiple datasets that are presented to the program as a single concatenation, for example, as follows:

//STEP4   EXEC PGM=DUMPCBL
//OUTFILE DD DSN=MYDATA.SAMPLE.RESULT,DISP=(NEW,CATLG),
//           SPACE=(TRK,(5,5)),LRECL=80,RECFM=FB
//INFILE  DD DSN=MYDATA.SAMPLE.FILE3,DISP=(OLD,CATLG)
//        DD DSN=MYDATA.SAMPLE.FILE2,DISP=(OLD,CATLG)
//        DD DSN=MYDATA.SAMPLE.FILE1,DISP=(OLD,CATLG)

Raincode JCL has two ways to represent concatenated files: logical concatenation (the default) or concatenating into a temporary file.

There are two ways to control the choice of whether or not to use temporary files for concatenated datasets:

  1. Globally: by the usage of the Submit parameter UseTempsForConcatenate=true|false

  2. For one specific program: by creating a .rcexe description (refer to .rcexe files) and include a tag `< UseTempForConcatenated>true|false</UseTempForConcatenated>

The specific configuration overrides the global configuration.

Further, these two approaches are explained in more detail.

2.2.1. Using logical concatenation

Raincode JCL and runtime (COBOL, PL/I, and HLASM) have logical concatenation as a default. When a concatenated dataset is declared, the Submit command passes a list of the data files to the program. The runtime system of Raincode can transparently read from the different files of the concatenation as needed.

In sample, the DUMPCBL program will receive DD_INFILE=MYDATA/SAMPLE/FILE3.seq;MYDATA/SAMPLE/FILE2.seq;MYDATA/SAMPLE/FILE1.seq

The significant advantage of this approach is that additional disk space or CPU time is not required to create a concatenated temporary file. The disadvantage is that the executed program must know and manage that list convention. This applies to any Raincode program but may not be apply to third-party tools.

2.2.2. Using a temporary file

The alternate approach is creating a temporary file to concatenate data into one file. Then, that single file will be passed as a parameter for the INFILE DD.

The advantage is that any called program sees only one input file for any DD, while the disadvantage is that the temporary file needs disk space and time to build.

2.3. Dataset Migration

This section explains migrating datasets from the mainframe to the Raincode catalog.

2.3.1. Transferring Datasets

To transfer a given dataset from the mainframe, use FTP in binary mode. If the dataset Variable Block (VB), ensure to use literal site RDW to transfer the Variable Record Descriptors, e.g.:

ftp mainframe.mycompany.com
ftp> binary
200 Representation type is Image
ftp> literal site RDW
200 SITE command was accepted
ftp> get MYFILE

2.3.2. Sequential dataset

To migrate a sequential dataset, follow these steps:

  • Transfer the file from the mainframe to the target machine, as described above in the section Transferring Datasets

  • Write a JCL to copy the recently transferred file into the catalog using the IEFBR14 utility. Ensure that the correct file attribute (LRECL and RECFM) is given. For example:

//LOAD3    EXEC PGM=IEFBR14
//DD00     DD  DSN=GRP.GMINI$10.MGAA1,
//             DISP=(NEW,CATLG,DELETE),
//             DCB=(LRECL=80,BLKSIZE=27920,RECFM=FB),
//             PATH=('C:\myfile',COPY)

2.3.3. VSAM dataset

To migrate a VSAM dataset, follow these steps:

  • On the mainframe, copy the data from the VSAM file to a sequential one

  • Migrate the sequential dataset, as described above in the section Sequential dataset

  • Write a JCL to create the empty VSAM file. For example:

//STEP003  EXEC PGM=IDCAMS
//SYSPRINT DD  SYSOUT=*
//SYSIN    DD  *
 DEFINE    CLUSTER (NAME(DATA3.ACCOUNT) INDEXED -
                    RECORDSIZE (80 80)  -
                    KEYS (19 0) ) -
           DATA     (NAME(DATA3.ACCOUNT.DAT)) -
           INDEX    (NAME(DATA3.ACCOUNT.IDX))
  • Write a JCL to copy the temporary sequential file into the VSAM one. For example:

//STEP004  EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SORTIN   DD   DSN=TEMP.VSAM,DISP=SHR
//SORTOUT  DD   DSN=DATA3.ACCOUNT,DISP=SHR
//SYSIN    DD  *
  REPRO IFILE(SORTIN) OFILE(SORTOUT)

2.3.4. Importing a line separated file into an Fixed Block dataset

Sometimes, Raincode receives ASCII line separated files, but these files need to be cataloged as a Fixed Block (FB) dataset. This is generally not a good idea; Raincode prefers receiving files in a binary (EBCDIC) format. However, Raincode has a special dataset type call LSEQ, a dataset where an ASCII line feed separates each record.

To migrate a line separated file into an FB dataset, you can follow the following steps:

  • Copy the file into the catalog using the IEFBR14 utility. The RECFM should be LSEQ.

//STEP1    EXEC PGM=IEFBR14
//         DD  DSN=A.B,
//             DISP=(NEW,CATLG,DELETE),
//             DCB=(LRECL=252,RECFM=LSEQ),
//             PATH=('C:\myfile',COPY)
  • Copy the LSEQ dataset into an FB dataset using IDCAMS

//STEP2    EXEC PGM=IDCAMS
//INF      DD  DSN=A.B,DISP=SHR
//OUTF  DD   DSN=A.C,
//             DISP=(NEW,CATLG,DELETE),
//             DCB=(RECFM=FB,LRECL=252)
//SYSIN    DD *
  REPRO    INFILE(INF) OUTFILE(OUTF)
/*

2.3.5. Continuation in JCL

A JCL line cannot exceed 72 characters. However, Windows and Linux file paths can be much longer. To handle this, you can split the path across two lines. The second line should not begin with //, but must start with at least two spaces.

// PATH=('c:\a\very\lonnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
           g\path.txt',COPY)

2.4. ASA print file vs ASCII print file and LSEQ vs VLSEQ

On the mainframe, print files are stored in FBA files using the ASA printer control character as the first character in the record. Usually, these files are produced by the report writer of COBOL programs that will use WRITE ADVANCING statements.

On the other side, windows and open system printers do not understand the ASA control char, and therefore, printing the resulting FBA requires a conversion. It is worth considering whether to use line sequential or variable line sequential files.

Below are the various aspects of handling print files.

2.4.1. Change the RECFM of the target file

Let’s suppose the following JCL step:

//STEP001  EXEC PGM=COB001
//RPT01    DD   DSN=A.B,DISP=(NEW,CATLG,DELETE),LRECL=133,RECFM=FBA

where COB001 produces a report in the A.B file, this will generate an FBA file containing an ASA character, a first character and 132 printable characters per line.

If you replace RECFM=FBA with RECFM=LSEQ

//STEP001  EXEC PGM=COB001
//RPT01    DD   DSN=A.B,DISP=(NEW,CATLG,DELETE),LRECL=133,RECFM=LSEQ

The produced file A.B will be an ASCII print file where controls use LF/CR/FF, which are ASCII control characters. The LRECL should not be changed as LSEQ will include 132 printables and 1 LF character at the end of the record.

The produced files are not FBA-compatible. Typically, the number of records will be greater, and the structure of the record is different. Therefore, this solution may only be used if the produced file is printed as-is, and no other program needs to read and process the result while assuming it is an FBA.

2.4.2. Convert the FBA to an ASCII print file using IDCAMS

In some cases, the change of RECFM is unacceptable because further steps use the produced file to read it and process or add other information. Changing the format may break the logic, and the JCL has a chance to fail.

Another solution is to convert the FBA ASA print file to the LSEQ ASCII print file at the end of the job. To do so, use IDCAMS REPRO utility with the CONVERT verb:

//STEP001 EXEC PGM=COB001
//RPT01    DD   DSN=A.B,DISP=(NEW,CATLG,DELETE),LRECL=133,RECFM=FBA
…
//STEP04   EXEC PGM=IDCAMS
//INF      DD  DSN=A.B,DISP=SHR
//OUTF  DD   DSN=A.C,
//             DISP=(NEW,CATLG,DELETE),
//             DCB=(RECFM=LSEQ,LRECL=133)
//SYSIN    DD *
  REPRO    INFILE(INF) OUTFILE(OUTF) CONVERT
/*

In STEP04, the IDCAMS REPRO utility, using the CONVERT command, reads the FBA file and converts ASA characters to output the equivalent file as an ASCII print file.

CONVERT only works if the input file is an FBA, VBA, FBM or VBM file and the target is an LSEQ or VLSEQ file.

2.4.3. LSEQ or VLSEQ

To handle print files, Raincode supports two line sequential files that are usable in RECFM.

  • LSEQ is a fixed record size line sequential. The record is fixed size padded with space, and the last character is an LF (ASCII Line Feed ).

  • VLSEQ is a variable record size line sequential. The record is variable size trimmed: all trailing space is removed, and the last character is an LF (ASCII Line Feed). Unlike VB files, no size is written at the beginning of the record. The size is computed when the first LF is read.

3. Submit

This section describes the relevant workings of Submit, the equivalent of the mainframe’s SUBMIT command, allowing users to submit a JCL for execution. In the beginning, various aspects of its use are described, and the end of this section contains the list of current command-line options for Submit.exe (as generated by Submit.exe itself).

3.1. Resolution of PGM=xxx

Each step of a JCL that includes PGM=<name> requires Submit to map the name to an external program to execute. To do so, Submit performs a lookup for a filename in the form <name>.<extension>, in the order of the following table:

Table 1. Executable lookup order by type

EXTENSION

FILE TYPE

REMARK

rcexe

XML

See .rcexe files

ps1

PowerShell script

sh

Linux sh script

bat

Windows batch file

Windows only

js

` VB Cscript

Windows only

vbs

VB Cscript

Windows only

wsh

VB Cscript

Windows only

dll

.Net assembly

Windows dll

exe

Binary executable

Windows only

No extension

Binary executable

Linux only

Submit looks for the file in the directories in the order listed in the following table.

Table 2. Executable lookup paths

LOCATION

REMARK

STEPLIB

The path defined in the step’s STEPLIB, if defined

JOBLIB

The path defined in the JCL’s JOBLIB, if defined

Executable Search Paths

The path list defined in the attribute executableSearchPaths of the catalog.configuration.xml

submit.exe path

The path of the running Submit.exe

JCLLIB

JCLLIB definition allows coding a set of libraries to find procedures and includes

Current working directory

The current working directory of the Submit process

3.1.1. .rcexe files

The execution of a program in Raincode JCL is controlled by files with the .rcexe extension, which provides meta-data that controls how the program is to be executed. Among other capabilities, this allows one to redirect the execution of any given program to alternate executables. This .rcexe file is an XML file.

The root element of the file is an RCLaunch element, and it may contain a number of child elements. All of these child elements are optional.

The type of XML elements allowed in a .rcexe file are described in the following table:

Table 3. XML elements in RCLaunch
XML ELEMENT DESCRIPTION

ExecutablePath

The full path to the executable is specified here.

If the ExecutablePath is empty, the executable name is derived from the .rcexe file name where .rcexe is replaced by .exe (on Windows) or .dll or no extension (the first match will be used). If the path is relative, the full path of the .rcexe file will be used as a base.

Arguments

The arguments that are passed to the executable when it is called.

WorkingDirectory

This is a working directory; if it is not specified, the directory used will be the same as the one for Submit.

ParametersAsEnvVar

Are the parameters PARM=(…​) only passed as environment variables in RC_PROC_PARM? If this is false (the default), they are also passed as command line parameters.

ExecMode

Execution Mode:

  • Direct: Call ExecutablePath directly (default).

  • RcUtility: Similar to direct but assumes assembly inherited from Raincode.Batch.Utilities.Common.

  • RcInternal: This would be valid for assembly inheriting from Raincode.Batch.Utilities.Common, use a direct call to IntenalExec in the process of Submit. This should only be used by the Raincode utilities.

  • rclrun: This will be called using the rclrun executable (or the user-defined runner set in the Catalog configuration).

UseTempForConcatenated

Use temporary files for concatenated DDs (see the section on Concatenated datasets)

Alias

This command is just an alias of the name provided. For Example, IKJEFT01A is an alias of IKJEFT.

If an alias is present, no other elements are needed. This alias itself will represent the command that is actually executed.

DisableSysoutRedirect

Disables the capture of stdout of the executed command to store it in the SYSOUT Dataset. The default is false.

When false, Submit redirects the executing command’s stdout and stores the content into the file defined by the SYSOUT DD card.

When set to true, Submit does not redirect stdout and does not open SYSOUT. The application is responsible for managing the SYSOUT.

DisableSyserrRedirect

Same as DisableSysoutRedirect for SYSERR.

For example, the file below specifies that the program name Myprog is mapped to the windows program c:\somepath\myexec.exe, and it will use temporary files for concatenation.

MYprog.rcexe
<?xml version="1.0" encoding="utf-8" ?>
<RCLaunch>
  <ExecutablePath>c:\somepath\myexec.exe</ExecutablePath>
  <UseTempForConcatenated>true</UseTempForConcatenated>
</RCLaunch>

3.1.2. Treatment of dll files

If Submit encounters a .dll, it is supposed to be a .Net assembly. Submit inspects the assembly to determine if it contains a Raincode legacy signature (e.g. it is generated by a Raincode legacy compiler).

If the legacy signature is found, Submit will use the runner to execute the DLL. If the signature is not found, the DLL will be executed using the dotnet(.exe) command-line utility.

3.2. Job Scheduler Integration

To allow integration with an external scheduler, Submit.exe returns the return code of the job that it executes. Therefore, to integrate with a job scheduler application, follow the instructions for executing a console application and use Submit.exe as the executable.

3.3. Job outputs

By default, the job outputs, i.e. the contents of SYSOUT for a job, are located in the C:\ProgramData\Raincode\Batch\Sysout directory. Each job that has been executed will have a specific folder containing the SYSOUT info.

Each folder in SYSOUT will contain the following:

  1. MSGLOG: The standard output from running a job.

  2. SYSLOG: Job information, job step statistics, and over job statistics display.

  3. SPECIFIED STEP: Specific sysout as defined by the job JCL.

  4. JCL LISTING: JCL for the job being run.

  5. StepActivity.json: Detailed information regarding the step activities of a job. They are used for restart.

  6. StepDDActivity.json: Detailed information regarding the DDs of each step of a job. They are used for restart.

3.4. JCL job repository

Submit includes the ability to build a database repository that archives several tables of the submitted JCL job, like job steps, conditions, procedures, etc. This repository can be used to analyze the portfolio and estimate the required workload for a migration effort.

Repository generation is only available when the -ScanOnly option is used along with the -DBDriver and -DBConnectionString command-line options. The DBDriver options specifies the desired type of database driver, and DBConnectionString specifies the desired connection string for the database.

The first database driver that can be used is SQLite, e.g., as follows:

Submit.exe -File=.\JOB.JCL -ScanOnly -DBDriver=Sqlite

When using SQLite as the database driver, the repository will be created in the same directory where Submit.exe is executed under the default repository name: RC_JCL_INVENTORY.db. However, one can specify the name of the database file through the DBConnectionString option.

Alternatively, an ODBC driver can be used, e.g., as follows:

Submit.exe -File=.\JOB.JCL -ScanOnly -DBDriver=ODBC -DBConnectString="DSN=odbcConnect"

When using the ODBC driver, the target database is an SQL Server. On the server side, one needs to create a database named: RC_JCL_INVENTORY and define the ODBC data source for the connection before executing Submit.exe. This data source needs to be passed as part of the DBConnectionString option.

The created repository includes several SQL tables giving viable information about the submitted jobs. For more details, refer to the appendix JCL JOB repository.

3.5. JCL dataset Locking

Raincode JCL emulates the locking mechanism of mainframe JCL on datasets using two-step lock file acquisition. Therefore, no changes must be made to the JCL batches to work with Raincode JCL. In order to prevent deadlocks, locks are obtained upfront at the beginning of the job, and taken in alphabetical order based on DSNAME.

3.5.1. Locks and the file system

Recall that Raincode JCL represents each dataset by a pair of files: the data file (.seq), and the meta file (.meta), as described in the Mainframe file system emulation. When a lock is obtained on a dataset, Raincode JCL will only lock the meta file.

The lock files are located in a special directory structure that exists for each volume defined in the catalog. This structure includes a directory named _lock, which is a subdirectory of the volume’s root. To lock a dataset, lock files will be placed in the _lock directory.

The _lock directory is not addressable via JCL and should only contain lock files.
Spurious locks, i.e. files being considered locked when they are not, can be removed by removing the corresponding lock files in the _lock directory. Alternatively, all locks can be removed by deleting the _lock directory.

The locking mechanism is also accessible programmatically. When developing utilities that involve catalog manipulation, developers should use the lock facilities by referencing the Raincode.Batch.LockingClient assembly and using its exposed interface. Similarly, when developing applications not called from a JCL but still interacting with the catalog, the developer needs to take care to lock and unlock files that will be accessed. This can be done using the LockingManager static methods from the Raincode.Batch.Catalog assembly.

3.5.2. Implementation of Locking

Raincode uses a lock file system as a semaphore to manage locking on the meta file. There are two lock files for a meta files: the shared lock file (.ls) and the exclusive lock file (.le).

The shared lock file represents that a process has a shared lock on a dataset. The exclusive lock file is the semaphore to the shared lock file, and both represent that an exclusive lock is owned or that a file is in the process of acquiring a shared lock.

The main principle is that all lock manipulation follows a two-step process (as illustrated in the figure Locking process):

  1. Obtaining a lock to exclusively lock the exclusive file.

  2. Once the lock on the exclusive file is obtained, try to acquire a lock on the shared file. The lock will be exclusive or shared, depending on the JCL level of locking needed.

image012
Figure 15. Locking process

Using the OS-provided locking mechanism removes the need for complicated bookkeeping by avoiding modifications to the files. All file opening are performed with a Delete on Close mechanism, usually provided by the operating system.

3.6. Command-line options for Submit.exe

Below are the details of the command line options of Submit.exe. These tables are automatically generated and contain the same information produced by running Submit.exe without arguments.

Debugger
Table 4. Details of command-line options for Submit in category Debugger
Command-line option Default value Description

AttachToProcess

False

Will launch JCL interpreter with the ability to attach JCL debugger later.

DebugJCL

False

Will launch JCL interpreter attached to JCL debugger. this is to enable JCL programs debugging (should only be used by IDEs or Debugger developers)

DebugServerIP

127.0.0.1

IP Address of host where JCL debug server will get hosted at, localhost will get used by default

DebugServerPort

9090

TCP port of JCL debug server, (default = 9090)

General
Table 5. Details of command-line options for Submit in category General
Command-line option Default value Description

AllowInternalCall

This command-line option enables calls to Raincode utilities to be performed in-process without the performance penalty of spawning a new external program. This option will only apply to some of the predefined utilities delivered together with Raincode JCL.

CatalogConfiguration

Specifies the path to the configuration file for the catalog. If the option is not specified, Submit checks for the value of the RC_BATCH_CATALOG environment variable. If this variable is found, its value is used as the path to the catalog configuration file.

CM_NCT2

True

This command-line option emulates the Control-M NCT2 function. RCS801 is the error code. Duplicate datasets will be cleaned at restart.

Comment

This command-line option lets users define comments that Submit will pass as an argument to the Raincode utilities it calls.

ControlM

True

Enables Control-M support. See also the EnhGDG and CM_NCT2 command-line option.

DDCheckSpace

False

If this command-line option control is enabled, Raincode JCL checks the presence of space parameter for DD with DISP=NEW/MOD.

This is used for strict mainframe compatibility.

DebugStep

Specifies the name of the step to debug. It causes a JIT debugger breakpoint to trigger when the step with a matching name is being executed.

DebugSubmit

False

Triggers a JIT breakpoint at the start of the Submit process. This can prove useful for debugging custom hooks.

DisableResolve

False

This command-line option forces the preprocessing of any JCL to start a state equivalent to %%RESOLVE(OFF).

DispSHRPermissive

False

Allows a disposition DISP=SHR to refer to a non-existing file, which will then be created on the fly.

DllLogLevel

Indicates the log level required from the runner (rclrun or other) when executing compiled COBOL, PL/I, HLASM or zTrieve programs.

DSN

Fully qualified dataset name for the JCL file to Submit.

EnableDDMetaFileInfo

Enable to store MetaFileInfo inside the DD information (default= true)

EnableFileCaching

True

Enables file I/O caching between steps.

EnableMetaCaching

True

Enables meta file caching between steps.

EnableMetaFlushing

Enable meta file flush(true) (default= false)

EnhGDG

True

Enables the emulation of Control-M’s support for GDG adjustment at restart.

ExecNameCaseInsensitive

True

(Linux Only) Enables case-insensitive matching when looking for a program.

File

Path to a source file containing the JCL to submit. This command-line option takes a valid file name on the current operating system (as opposed to a catalogued DSN). It can prove useful for bootstrapping an installation since it allows for the execution of a JCL which is not in the catalog.

FileExistsTryOpenFile

False

Indicates that FileStream.Open should be used to test for a file’s existence.

JclConverter

This command-line option provides a string to the JclConverter.xml configuration file. If this parameter is set, the given JCL will be translated into a new command format for the utilities.

JobID

This command-line option lets the user define the Job ID when there is an external scheduler.

JobName

Sets a different name to the job instead of using the default. In this case, the Job name on the job card is ignored.

KeepRestartInfo

Keep info about Name of the step to restart the job with after execution of the first step

KeepTempFiles

False

Retains the temporary files created by Raincode JCL instead of deleting them. To be used for debugging.

LogToConsole

This command-line option registers a log file listener that displays the log to the console.

LogToTrace

This command-line option registers a log file listener that displays the trace data to the Windows log trace facility.

MsgLogFlushInterval

-1

Sets the MSGLOG.txt and SYSOUT logfile flushing interval, expressed in seconds. A negative value for this parameter causes this logfile not to be flushed.

NoAdv

When using WRITE ADVANCING, use NoAdv if you already adjusted record length to include 1 byte for the printer control character

PortPool

500

Specifies the size of the pool of ports that can be used for tcp.net binding.

PortStart

18000

This command-line option specifies the port number of the first port for tcp.net binding.P

ProcLibs

Specifies the directory where PROCs should be looked for if not defined in the catalog.

RecordFormat

Specifies the record format of the file to submit using the -File option. This option also requires the -RecordLength option to be specified. Valid values are:

  • FB

  • VB

  • FBA

  • VBA

  • LSEQ

  • Unknown

  • VLSEQ

  • FBM

  • VBM

  • U

RecordLength

Specifies the record length for the file to submit using the -File option. It requires the -RecordFormat option to be specified as well. This option can be omitted if the selected record format is line sequential.

RelLockAtStep

True

Release file locks at the step level.

RepoConnectString

This command-line option specifies the connection string for the repository. See also the RepoDriver option.

RepoDriver

This command-line option sets the connection string for the repository persistence system as an ODBC connection string if ODBC persistence is used or as a physical file name if SQLite is used instead. See also the DBConnectString option. Valid values are:

  • ODBC

  • Sqlite

Restart

Specifies the name of the step where the job must be restarted. It overrides the RESTART= parameter in the JCL if present. To restart on a proc-step, the format STEP1.MYPROC should be used.

RestartJobId

Specifies the job ID that the user is attempting to restart. The restart JobID refers to the JobID of the previous execution that needs to be restarted.

RunToStep

Specifies the name of the final step of the JCL to execute. When a step with a matching name is encountered, it is executed, and the job is terminated. To specify a proc-step, the format STEP1.MYPROC should be used.

SaveJobID

Specifies the full path of SYSOUT folder.

ScanOnly

False

Activates the parsing and scanning of the JCL, disables any executions of the steps. This command is useful for checking a JCL for syntax and compatibility.

ServerIP

localhost

Specifies the IP address for the server that provides the locking service to connect to if not on the same machine.

Silent

False

Instructs the JCL interpreter not to output anything to the console. This does not affect the log.

StepProfilingInfo

False

This command-line option does step profiling info in a separate file.

SubstvarXml

Specifies the path to the XML file to be used for SUBSTVAR processing. This command overrides the setting in the catalog configuration for SubstitutionVariableFilePath.

SyslogXML

False

Activates the storage of the SYSLOG data in an XML format, with an XML extension. The file will be stored in the same directory as the SYSLOG (SYSLOG.<jobname>.TXT).

TruncateJCLAfter72

False

Truncating the JCL input stream at column 72. This allows the JCL to contain line numbers or comments after column 72, that will be ignored.

UseTempsForConcatenate

False

Requires the construction of a temporary file for the concatenated input.

UtilityLogLevel

Specifies the log level to use when running Raincode utilities.

ValidateJobID

False

Ensures that the user’s job ID has not already been used. If it is, the Job is stopped, and the return code is set to 16.

Volume

If set, this command-line option specifies the volume where DSNs are stored.

When a DSN is provided without specifying a volume, the default volume will be used. However, if the DSN is located on a different volume than the default, you will need to specify that volume as well.

Miscellaneous
Table 6. Details of command-line options for Submit in category Miscellaneous
Command-line option Default value Description

DateTimeOffset

This command-line option specifies the runtime’s time by initializing it with a specified datetime value, using an offset.

The DateTimeOffset allows the offset to be specified instead of the initial datetime.

DotNetConfigFile

This command-line option is an additional .net 'app.config' file.

DumpLicense

Checks and displays the current license.

Help

Displays the tool’s help information.

IgnoreUnkownArgs

Info

False

Displays a description of the program.

InitialDateTime

Specifies the date and time to use to give to the runtime, to be used instead of the system time. The format for this option is XXXXXXX.

LogLevel

INFO

Specifies the log level. Valid values are:

  • SILENT

  • ERROR

  • WARNING

  • PROGRAM_OUTPUT

  • PROGRAM

  • INFO

  • DEBUG

  • TRACE

  • DIAGNOSTIC

Version

False

Displays the version information.

Plugin
Table 7. Details of command-line options for Submit in category Plugin
Command-line option Description

Plugin

The list of plugins to be loaded when the tool executes.

PluginPath

This command-line option specifies the path to plugins that are searched.

Testing
Table 8. Details of command-line options for Submit in category Testing
Command-line option Description

DisableAssignProcessToJobObject

This command-line option, a boolean value, disables the call to AssignProcessToJobObject.

4. Catalog configuration

Submit relies on the catalog manager, among others, to perform its functions. The catalog manager emulates the catalog manager of the file system on the mainframe, i.e. it implements a view on the emulated file system that is part of Raincode JCL. The catalog manager can be configured using the catalog configuration file. It allows users to change default settings, such as units, volumes, record length, etc.

When Submit begins, it looks for the catalog configuration in the following sequence:

  1. If the command line option -CatalogConfiguration is provided, its parameter specifies the path to the catalog configuration file.

  2. If the environment variable RC_BATCH_CATALOG is set, its value is used as the path to the catalog configuration file.

  3. If neither of the above is set, the file in the default location C:\ProgramData\Raincode\Batch\Raincode.Catalog.xml for Windows, or /var/lib/Raincode/Batch/ Raincode.Catalog.xml for Linux, is used.

If the lookup fails, a Default catalog configuration file will be created in the default location, and this file will be used.

4.1. Default catalog configuration

Below is the default configuration file (for Windows at the time of writing this document) created if the lookup fails. It consists of a top-level CatalogConfiguration element with several relevant attributes and various nested entities, all of which are described in the remainder of this chapter.

<catalogConfiguration
  defaultRecordLength="80"
  defaultSysoutRecordLength="133"
  defaultSysprintRecordLength="133"
  truncateRedirectedSysoutRecord="true"
  ebcdicCompareCodePage="870"
  defaultOutputClass="A"
  defaultCodePage="1252"
  sysoutFolderPath="C:\ProgramData\Raincode\Batch\SYSOUT"
  sysoutVolumeName="#SYSOUT"
  sysoutSyslogVersion="1"
  noAdv="false"
  sysoutMetaKeep="true"
  ignoreUnitName="false"
  strictCatalogValidation="false"
  autoEditCalendarFolderPath="C:\ProgramData\Raincode\Batch\AutoEditCalendars"
  sysoutFolderNamingPattern="JOB{ID}"
  syslogNamingPattern="SYSLOG"
  defaultRecordFormat="FB"
  defaultSysoutRecordFormat="LSEQ"
  defaultSysprintRecordFormat="LSEQ"
  instreamDataRecordFormat="FB"
  instreamDataRecordLength="80"
  SDSN_Wait="3600"
  enforceMemoryRestriction="true"
  enforceUpdateLastReference="false"
  enforceSMSValidation="false">
  <units>
    <unit
      name="SYSDA"
      isDefault="true">
      <volumes>
        <volume
          name="DEFAULT"
          path="C:\ProgramData\Raincode\Batch\DefaultVolume"
          isDefault="true" />
      </volumes>
    </unit>
  </units>
  <defaultProcLibraries>
    <DSN>::SYS1.PROCLIB</DSN>
  </defaultProcLibraries>
  <SysoutMetaKeep>true</SysoutMetaKeep>
  <codePages
    jclAlternate="1252"
    jclRewrite="Default" />
</catalogConfiguration>

4.2. Catalog configuration description

The top-level CatalogConfiguration element can have several attributes, the meaning of which is described in the table below.

Table 9. Catalog configuration attributes
Tags Default Values Description

autoEditCalendarFolderPath

"Configuration_folder\AutoEditCalendars"

Path to the folder containing named calendar XML files. For more details, refer to the AutoEdit calendar configuration.

batchCustomPluginPath

Path to the folder containing the batch plugins.

batchCustomPlugins

Names of the plugins that are loaded when executing Submit. For more details, refer to the Plugin.

catalogDbConnection

If catalogFormat is db, this specifies the connection string for the database.

catalogFormat

disk

This tag is the catalog storage format. The accepted values are disk and db.
disk: the catalog is stored in the file system.
db: the catalog is stored in a SqlServer DB.

dbConnectionDataProvider

RcDbConnections.csv

The path to the CSV file is provided to map the PLAN name to the actual connection string. For more details, refer to the section Map a PLAN name to a connection string.

defaultAsciiCodePage

The default code page for interpreting ASCII data. If nothing is set, the DefaultCodePage will be used. For more details, refer to the section JCL character encoding.

defaultCodePage

1252

The default code page for interpreting text data. This is particularly useful for testing jobs that need to execute under a code page different from the current system. For more details, refer to the section, JCL character encoding.

defaultEbcdicCodePage

The default code page for interpreting EBCDIC data. For more details, refer to the section JCL character encoding.

defaultFileConfig

<defaultFileConfig> <MainFrameFBA>false</MainFrameFBA>
   <LineEndCRLF>false</LineEndCRLF>
   </defaultFileConfig>

Default File Config parameters

defaultOutputClass

A

The default output class for SYSOUT=*, if an MSGCLASS is not specified on the JOB card.

defaultRecordFormat

FB

Default record format. At the moment, only FB is supported.

defaultRecordLength

0

The default record length, if not specified, should be set to 0. If set to 0, it will be changed to 80

defaultSysoutRecordFormat

LSEQ

The default record format for SYSOUT (LSEQ=Line sequential).

defaultSysoutRecordLength

133

The default record length for SYSOUT datasets.

defaultSysprintRecordFormat

LSEQ

The default record format for SYSPRINT (LSEQ=Line sequential).

defaultSysprintRecordLength

133

The default record length for SYSPRINT datasets.

directoryTypeExtension

._dir

Extension for directory type datasets. (Only used if catalogFormat is disk.)

ebcdicCompareCodePage

870

The EBCDIC code page to use for comparing strings. This is used by AutoEdit conditional processing statements.

enforceMemoryRestriction

TRUE

This flag indicates whether or not a memory limit should be enforced for the process. Accepted Values: TRUE or FALSE.

enforceUpdateLastReference

FALSE

Enforce that the lastReferenceDate will be updated at any access to the data file. Accepted values: TRUE or FALSE.

instreamDataRecordFormat

FB

The default instream data record format, used if the JCL does not specify RECFM options.

instreamDataRecordLength

80

The default instream data record length, used if no DD parameters are set overriding the instream data record format in JCL.

isamDefaultDriver

Empty

Allows you to specify the default driver used for ISAM (flat, non indexed) file.

legacyRunner

%RCDIR%/bin/rclrun.exe

Path to the runner needed to run a COBOL, PL/I or HLASM program. This allows the use of a user-defined runner, as shown in the section Customizing Legacy Runner calls.

legacyRunnerParameters

Empty

Add additional parameters when invoking LegacyRunner. For more details, refer to the section Customizing Legacy Runner calls

SDSN_Wait

"3600"

Specifies the installation policy for batch jobs that must wait to enqueue the dataset (Locking). Values can be NO, YES, or 1-999999. For more details, refer to the section SDSN wait.

SMSConfig

"Configuration_folder"

Specifies the values of the SMS DD parameters (DATACLAS and STORCLAS). For more details, refer to section SMS Configuration.

substitutionVariableFilePath

Optional path to a file containing substitution variables. For more details, refer to the section Substvar.

sysoutFolderNamingPattern

"JOB{ID}.{NAME}"

Naming pattern to use when generating the SYSOUT folder name. For more details, refer to the section Sysout Folder Naming Convention.

sysoutFolderPath

"Configuration_folder\SYSOUT"

Path to a folder where job-specific SYSOUT files should be written.

sysoutMetaKeep

TRUE

If true, the SYSOUT meta file will be kept at the end of the step.
If false, the SYSOUT meta file will be deleted at the end of the step.

sysoutSyslogVersion

1

The version of the SYSLOG format in the SYSOUT folder.
1 = V1 OLD (status until 2022/04).
2 = V2 NEW (STEP logging changed PROCNAME).

sysoutVolumeName

#SYSOUT

Name of the volume used to store SYSOUT files.

truncateRedirectedSysoutRecord

TRUE

If true, truncate SYSOUT record to the length of SYSOUT when redirected to a file.
If false, SYSOUT record is split over several records if needed.

vsamDefaultDriver

Empty

Allows specifying the default driver for VSAM Indexed files when using something other than the default ISAM. For example, set the value to VsamLite to store Indexed files in an SQLite database.

The CatalogConfiguration element can have various nested entities, as described in the following table.

Table 10. Catalog configuration elements
Tags Values Description

autoDDCardDefinitions

Definition of DD cards for the step that is not explicitly declared in the JCL. For more details, refer to the section JCL Automatic DD card definition.

datasetSqlMapping

Datasets data that are stored into a database. For more details, refer to the section Dataset mapping with tables.

defaultProcLibraries

<defaultProcLibraries>
    <dsn>SYS1.PROCLIB</dsn>
  </defaultProcLibraries>

List of PDS libraries to search for PROCs. SYS1.PROC is always added as the last element.

environmentVariables

Environment variable values that Submit will set at the beginning of each step. For more details, refer to the section Environment Variables.

executableSearchPaths

Paths to use when looking for an executable in an EXEC statement. Each path is specified within a <path> subelement.

fileFormatExtensions

<fileFormatExtensions>
     <ext>.seq</ext>
     <ext>.idx</ext>
     <ext>.rr</ext>
     <ext></ext>
   </fileFormatExtensions>

List of file extensions for file formats, indexed by file format enum cast as int.

noLocking

List of DSN patterns on which locking must not be applied. The pattern is a simple IDCAMS pattern a.c.C.**.

programDBConnectionDefinitions

Define rules to associate programs and jobs to a default PLAN (by extension a connection String). For more details, refer to the section DB connection definition

recordFormatExtensions

List of file extensions for file types, indexed by file type enum cast as int.

Units

Units that are defined in the catalog. For more details, refer to the section Unit and Volume Configuration.

codePages

<codePages jclAlternate="1252"
jclRewrite="Default"
console=""
sysout=""
sysprint="" />

The default code page to use for interpreting ASCII data. This is particularly useful for testing jobs that need to execute under a code page different from the current System. For more details, refer to the section JCL character encoding.

4.3. AutoEdit Configuration

Raincode JCL includes support for the expansions of Autoedit variables in JCLs. In addition to the use of autoedit datasets, as on the mainframe, it looks up environment variables to find values when needed. For example, if a variable such as %%FOO could not be found in an autoedit dataset, the value of the CTM_FOO environment variable (if present) will be used instead. Additionally, the values for some variables set by Control-M , listed below, need to be specified through environment variables before they can be used in the JCLs.

Table 11. AutoEdit replacement variables

Parameter

Environment variable passed by Control-M

%%APPL

CTM_APPL

%%JOBNAME**

CTM_JOBNAME

%%ORDERID**

CTM_ORDERID

%%RN**

CTM_RN

%%TIME

CTM_TIME

%%$CENT

CTM_$CENT

%%DATE

CTM_DATE

%%DAY

CTM_DAY

%%MONTH

CTM_MONTH

%%YEAR

CTM_YEAR

%%WDAY

CTM_WDAY

%%ODATE

CTM_ODATE

%%ODAY

CTM_ODAY

%%OMONTH

CTM_OMONTH

%%OYEAR

CTM_OYEAR

%%OWDAY

CTM_OWDAY

%%RDATE

CTM_RDATE

%%RDAY

CTM_RDAY

%%RMONTH

CTM_RMONTH

%%RYEAR

CTM_RYEAR

%%RWDAY

CTM_RWDAY

%%JULDAY

CTM_JULDAY

%%OJULDAY

CTM_OJULDAY

%%RJULDAY

CTM_RJULDAY

%%$DATE

CTM_$DATE

%%$YEAR

CTM_$YEAR

%%$ODATE

CTM_$ODATE

%%$OYEAR

CTM_$OYEAR

%%$RDATE

CTM_$RDATE

%%$RYEAR

CTM_$RYEAR

%%$OJULDAY

CTM_$OJULDAY

%%JOBID

CTM_JOBID

Autoedit calendars are also supported. By default, they are read from the C:\ProgramData\Raincode\Batch\AutoEditCalendars path, but this behavior can be overridden by using the the autoEditCalendarFolderPath attribute in the catalog configuration.

The example configuration file below shows the expected structure of such a calendar file. The important part is the NAME= property since it maps to the calendar name that AutoEdit uses.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE DEFCAL SYSTEM "defcal.dtd">
<DEFCAL>
  <CALENDAR DATACENTER="enterprise" NAME="MYCALENDAR" TYPE="Relative">
    <YEAR NAME="1999" DAYS="NNNNYYYYNYYYYYYYYNNNNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYNYYYYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYYYYY" DESCRIPTION="This is year 2000"/>
    <YEAR NAME="2000" DAYS="YYNYYYYYNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYNYYYYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYYYYY" DESCRIPTION="This is year 2000"/>
    <YEAR NAME="2001" DAYS="YYNYYYYYNNNNNYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYNYYYYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYNYYYYYYYYYYYYYYYYYYYYYYY" DESCRIPTION="This is year 2001"/>
  </CALENDAR>
</DEFCAL>

Alternatively, the IAutoEditCalendar interface can be implemented and registered in the submit.exe.config file to perform the supported calendar operations. The default implementation uses the XML file format from Ctrl-M. It only supports the relative type format shown above.

4.4. Bootstrapping your Environment: An Example

Bootstrapping your environment typically consists of creating one or multiple PDS libraries and importing existing JCL files into the PDS libraries created. Below is an example of such a JCL bootstrap job.

//BOOTSTRAP  JOBID
//*
//* This job is used to bootstrap the batch environment
//*
//* First we create the PDS Library
//STEP1A  EXEC PGM=IEFBR14
//DD1     DD DSN=NIMBLE.TEST.JCL,DSNTYPE=PDS,
//        DISP=(NEW,CATLG,DELETE),RECFM=LSEQ,VOL=SER=DEFAULT
//*
//* Second, we import the JCL files using a DD Path option
//STEP2   EXEC PGM=IEFBR14
//DD1     DD DSN=NIMBLE.TEST.JCL(CONDEXEC),DISP=(,CATLG,DELETE),
//        PATH=('.\JCL\CONDEXEC.JCL',COPY)
//*
//DD2     DD DSN=NIMBLE.TEST.JCL(CONDJOB),DISP=(,CATLG,DELETE),
//        PATH=('.\JCL\CONDJOB.JCL',COPY)
//*
//DD3     DD DSN=NIMBLE.TEST.JCL(DCBINFO),DISP=(,CATLG,DELETE),
//        PATH=('.\JCL\DCBINFO.JCL',COPY)
//*

4.5. Running programs from JOBLIB and STEPLIB

When a JOBLIB or STEPLIB is specified in the JCL, Submit first searchesthe specified libraries for executables (for more details, refer to the Resolution of PGM=xxx) . For this feature to function properly, it is necessary to define the corresponding libraries in the catalog, and load them with the program binaries (DLLs). You can create a PDS library (in this case named ENV.DEV) as shown below:

//CREATELIB  JOB
//*
//STEP0    EXEC PGM=IDCAMS
//SYSPRINT DD  SYSOUT=*
//SYSIN    DD  *
  DELETE ENV.DEV
  SET MAXCC=0
//*
//STEP1   EXEC PGM=IEFBR14
//DD1     DD DSN=ENV.DEV,DSNTYPE=PDS,
//        DISP=(NEW,CATLG,DELETE),RECFM=LSEQ

Assuming that you have a COBOL source file named HELLO.cob, which has been compiled into HELLO.dll, the compiled file must be copied to the PDS library ENV.DEV, located at <default volume>\ENV\DEV._dir\.

At this point, the library is ready to be used. You can then create a JCL to execute a program from this library. For example:

//Hello    JOB Hello, COND=(4,LT)
//STEP01   EXEC PGM=Hello
//SYSPRINT DD SYSOUT=*
//STEPLIB  DD DSN=ENV.DEV,DISP=SHR

The resulting PDS library can, of course, be also used for JOBLIB.

4.6. Dataset mapping with tables

When using the VSAMSql, VSAMLite, and VSAMOracle drivers (see chapter VSAMSql), the dataset must be defined to use the VSAMSql driver to store data in a database instead of on the file system. This mapping information is stored in the <datasetTemplate> element under <datasetSqlMapping>.

The <datasetTemplate> element contains several attributes:

  • connection: the plan for the connection string, see section Map a PLAN name to a connection string

  • tableName: the name of the table in which the data is stored.

  • commitRate: the number of inserts to be done before a commit. If it is set to -1 (the default), the commit is only done when the file is closed.

  • driver: the driver to be used. The default value is VSAMSql.

  • cache settings: see the VSAMSql Cache configuration section for more information.

<datasetTemplate> contains one or more <pattern> elements, one <parameters> element, zero or one <partitions> elements and zero or more <driverParameter> elements.

An example is below:

  <datasetTemplate tableName="REC_AREA" connection="VSAMDEAL">
    <pattern>
        <DSN>VSAM\.AREA\..*</DSN>
    </pattern>
    <pattern>
      <volume>DEFAULT</volume>
      <DSN>VSAM\.RECAREA</DSN>
    </pattern>
    <parameters length="316">
      <key start="1" length="10"/>
      <altKey start="305" length="5" unique="Y"/>
    </parameters>
  </datasetTemplate>

The different entities in the datasetTemplate entity are as follows:

  • <pattern> describes the dataset name that must be stored in the table. It contains at most one <volume> element that gives the name of the volume. Use the default volume if there is no <volume> element. It contains one <DSN> element, a regex representing the DSN stored in this table.

  • <parameters> describes the maximum size of the records and their keys. The attribute length is the maximum length of the records. The optional element <key> defines 0 based position (start) and the size (length) of the key. And zero or more elements <altKey> define the 0 based position (start) and the size (length) of the alternated key. The unique attribute is set to Y or YES if the alternate key is unique, otherwise it is set to N or NO.

  • <partitions> describes the mapping between the file names and the partition number (see Partitions). It’s composed of one or more <partition> elements. The <partition> element contains the following attributes:

    • id: the id of the partition

    • volume: the volume of the file

    • DSN: the DSN of the file (without wildcard)

  • <driverParameter> is used to give parameters to the driver. These additional parameters can be specific to a job, a step or a program. The additional parameters are conditional, based on a matching regular expression on Program Name, StepId, and JobId. This is done through the definition of attributes on driverParameter, all of which are optional. See the table below.

Table 12. driverParameter attributes
Attribute name Function Type Typical Value

jobId

Regular expression to be matched on the current Job ID

Regular expression string

00X1..

jobName

Regular expression to be matched on the current Job Name

Regular expression string

TSK01.*

pgm

Regular expression to be matched on the current PGM=clause

Regular expression string

PRG001

stepId

Regular expression to be matched on the current Step ID

Regular expression string

0001.*

Considering the contents of driverParameter: it should be a valid XML and is passed to the file driver as it is. The VSAMSql allowed elements are:

  • connectionGroup: a group can be associated with a file. All the files that belong to the same group use the same DB transaction, i.e., all the tables storing the data are committed together.

  • commitReadNext: if it is set to 1 for a file, each time a record of this file is read, the connection group to which this file belongs is committed.

  • commitRate: the number of inserts to be done before a commit. If it is set to -1, the commit is only done when the file is closed. It overrides the value of the attribute of datasetTemplate.

In addition to the above mentioned parameters, cache configuration parameters can also be specified, as detailed in the VSAMSql Cache configuration section.

Tables creation

Before using the VSAMSql/VSAMOracle files, tables need to be created. VSAMLite creates the tables on the fly. The driver does not do the table creation because the people executing a program usually don’t have the right to create tables; that’s why there is a program, VsamSql.DbGenerator reads the catalog configuration and generates the table creation script (see Database creation). This script needs to be executed by somebody (DBA, for example) that has the right to create tables.

4.7. Dataset mapping for DSN to Volumes

If the volume (VOL-SER) is not defined in the DD statement, the dynamic distribution for files occurs as mentioned below.

The <defaultVolumeMapping> element contains the following attributes:

  • defaultVolume: contains two entries, DSN and Volume

  • DSN: the string that will be checked against the DSN name.

  • Volume: the Volume name where the file will be stored. For this entry, a UNIT definition must exist.

An example is illustrated below:

  <defaultVolumeMapping>
   <defaultVolume>
    <DSN>SYS.TEMP</DSN> <volume>Disk1</volume>
   </defaultVolume>
   <defaultVolume>
    <DSN>NNNN.DISK</DSN> <volume>Disk1</volume>
   </defaultVolume>
   <defaultVolume>
    <volume>Disk2</volume> <DSN>MMMM.DISK</DSN>
   </defaultVolume>
  </defaultVolumeMapping>
  <units>
    <unit
      name="SYSDA"
      isDefault="true">
      <volumes>
        <volume
          name="DEFAULT"
          path="C:\ProgramData\Raincode\Batch\DefaultVolume"
          isDefault="true" />
        <volume
          name="Disk1"
          path="C:\ProgramData\Raincode\Batch\Disk1"
          isDefault="false" />
        <volume
          name="Disk2"
          path="C:\ProgramData\Raincode\Batch\Disk2"
          isDefault="false" />
      </volumes>
    </unit>
  </units>

The example above explains the following:

  • If DSN starts with SYS.TEMP or NNNN.DISK, it will be physically stored on DISK1. The default path is C:\ProgramData\Raincode\Batch\Disk1.

  • If DSN starts with MMMM.DISK, it will be physically stored on DISK2. The default Path is C:\ProgramData\Raincode\Batch\Disk2.

The DSN will be stored in the defaultVolume if none of the above DSN is specified.

<DSN> refers to the dataset name that must be stored on the specified volume. It contains a <DSN> element, a regular expression (regex) representing the DSN stored in this volume.

4.8. Environment variables for steps

The catalog configuration defines environment variable values that Submit will set at the beginning of each step such that the executing program can retrieve this information if needed. Below is an example.

<environmentVariables>
    <envvar name="Name1" stepId="StepRegEx">Test1Value</envvar>
    <envvar name="Test2" pgm="PRGB1">Test2Value</envvar>
    <envvar name="Test3" pgm="PRGA.*">Test3PRGA</envvar>
    <envvar name="Test3" >Test3OTHER</envvar>
</environmentVariables>

<environmentVariables> is a list of <envvar> elements. These have one mandatory attribute: Name, which is the name of the variable, and a set of optional attributes, as defined in the table below.

Table 13. List of optional environment variables attributes
Attribute name Function Typical Value

jobID

Regular expression to be matched on current JobID

00X1..

jobName

Regular expression to be matched on current Job Name

TSK01.*

pgm

Regular expression to be matched on current PGM=clause

PRG001

stepID

Regular expression to be matched on the current StepID

0001.*

The value of the environment variable is the character data inside the <envvar> element.

The name attribute is mandatory, and the other attributes are optional.

The definition of environment variables and their values is conditional, based on regular expressions on Program Name, StepID, and JobID. If several regular expressions are defined for one <envvar> (e.g., stepId= "0001.*" and PGM="PRG01"), all of them must match to define the environment variable.

If no regular expression is given, the environment variable is always defined.

The list of <envvar> is evaluated in the order it appears in the .xml. If the same name attribute exists multiple times, only the first match is used.

4.9. JCL Automatic DD card definition

The mainframe can define a DD card for a step not explicitly declared in the JCL. The catalog supports this through the <autoDDCardDefinitions> section containing <ddCard> elements. An example is illustrated below.

  <autoDDCardDefinitions>
    <ddCard name="AUTO1" RECFM="FB" LRECL="120"/>
    <ddCard name="AUTO2" />
  </autoDDCardDefinitions>

The ddCard element defines a dataset in the SYSOUT directory. It has one mandatory attribute: Name, which is the DD card name, and a set of optional attributes, as defined in the table below.

Table 14. List of optional ddCard attributes

Attribute name

Function

Typical Value

jobID

Regular expression to be matched on current JobID

00X1..

jobName

Regular expression to be matched on current Job Name

TSK01.*

pgm

Regular expression to be matched on current PGM=clause

PRG001

stepID

Regular expression to be matched on the current StepID

0001.*

RECFM

RECFM= format to use for the DD card (FB, VB …). Default is the format of SYSOUT

FB

LRECL

LRECL= value to use for the DD card. Default is the value of `SYSOUT`120

If several regular expressions are defined for one <ddCard> (e.g., stepId= "0001.*",PGM="PRG01"), all of them must match to define the DD card.

If no regular expression is defined, the DD Card is always defined.

4.9.1. Example

If <ddCard name="AUTO1" RECFM="FB" LRECL="120"/> is defined and the JCL is:

//SIMPLE   JOB  CLASS=A,MSGCLASS=C
//STEP1    EXEC  PGM=TST01

The JCL would be equivalent to the following:

//SIMPLE   JOB  CLASS=A,MSGCLASS=C
//STEP1    EXEC  PGM=TST01
//AUTO1  DD RECFM=FB,LRECL=120,SYSOUT=*

This will create a file:

For JCL 4.1:

SYSOUT/JOB0000000001.SIMPLE/STEP1.AUTO1.meta
SYSOUT/JOB0000000001.SIMPLE/STEP1.AUTO1.txt

As of JCL 4.2:

SYSOUT/JOB0000000001-SIMPLE/STEP1/AUTO1.meta
SYSOUT/JOB0000000001-SIMPLE/STEP1/AUTO1.seq

4.10. JCL connection string retrieval

When a program using a DB is used, it requires a connection string and a DB Type to pass to rclrun. On the mainframe, this is typically defined by a configuration that associates a Job or Program Name to a Plan Name, while in IKJEFT01, PLAN (xxx) lets a user define the Plan name that will determine the connection to the DB. This section provides insights into how this is done in Raincode JCL.

4.10.1. Global DB connection definition

For development and debugging or demo purposes, the simple way to define the connection string is to use environment variables. Setting them defines a global connection string that will be used by Submit and rclrun.

Define:

RC_DB_TYPE = [SqlServer/DB2/Postgres]
RC_DB_CONNECTION = <The connection string that will correspond to the DB engine defined by RC_DB_TYPE>

Example:

RC_DB_TYPE = SqlServer
RC_DB_CONNECTION = "Data source=sqlsrv2017; Initial Catalog=PLICompilerTestDB; Uid=****; Pwd=*******"

When calling rclrun, IKJEFT01 will build the command line using the connection string:

RCLRUN.exe -SqlServer="Data Source= sqlsrv2017; Initial Catalog=PLICompilerTestDB; Uid=****; Pwd=*******"
If PLAN is resolved, the new connection string will be used; otherwise, the environment variable will be used.

4.10.2. Local DB connection definition

In contrast to a global connection definition, a local connection definition is more like the mainframe production environment.

Raincode JCL emulates the mainframe connection definition and PLAN by using two attributes of the catalog configuration: dbConnectionDataProvider and programDBConnectionDefinitions. These attributes are presented next.

Map a PLAN name to a connection string

The dbConnectionDataProvider attribute in the catalog configuration defines a mapping from PLAN names to connection strings. In this file, PLAN names are C# regular expressions linked to a connection string.

Lookup for this file is performed in the following order:

  1. In the catalogConfiguration element of the catalog configuration, the value of the attribute dbConnectionDataProvider, if it exists.

  2. An environment variable RC_DB_FILE containing the path, if it exists.

  3. The default file name: RcDbConnections.csv

The file uses a standard RFC 4180 comma-separated format without header, with one plan mapping per line with the following fields:

<PLAN regex pattern>,<DB Type>,<Connection String>
If the connection string contains commas, it must be enclosed in double quotes to ensure proper CSV parsing.
Lines beginning with # or // are considered comments and are ignored and can be used to annotate the file as needed.

Supported values for <DB Type> are: SqlServer,DB2 and Postgres.

Example entries are as follows:

 PLANA01,SqlServer,"Data Source=sqlsrv2017; Initial Catalog=PlICompilerTestDB"
 PLANB.*,SqlServer,"Data Source=sqlsrv2017; Initial Catalog=CPTTestDB"

The list of mappings is evaluated in the order the entries are written in the file. The first entry that matches the regular expression on the PLAN Name is used.

Before execution of any step after the change of the connection string by IKJEFT01, the environment variable is set to actual connection values:

RC_DB_TYPE=<DB Type>
RC_DB_CONNECTION=<connection string>
Map a Job or program to a PLAN

The programDBConnectionDefinitions element in the catalog configuration contains a list of dbConnections elements. Each of these allows to define a mapping from jobId and/or ProgramId, and/or stepId using a C# regular expression to a PLAN Name. This is done through the definition of attributes on dbconnection, all of which are optional.

Table 15. dbConnection attributes

Attributes

Description

Type

jobId

Regular expression to be matched on current JobID

Regular expression string

jobName

Regular expression to be matched on current Job Name

Regular expression string

pgm

Regular expression to be matched on current PGM=clause

Regular expression tring

stepId

Regular expression to be matched on the current StepID

Regular expression String

The value of the plan name is the character data inside the element.

The elements are evaluated in the order of their appearance in the configuration file, and the first match is used. If an entry does not specify a given attribute, matching will succeed for any value of that attribute.

An example list of definitions is as follows:

< programDBConnectionDefinitions >
    <dbConnection pgm="PRGB1">PLANA01</dbConnection >
    <dbConnection pgm="PRGA.*">PLANA02</dbConnection >
    <dbConnection JobId=".*" >PLANOTHER</dbConnection >
 </programDBConnectionDefinitions >

Since <dbConnection pgm="PRGB1">PLANA01</dbConnection> only specifies pgm, any jobId, any JobName, and any StepId are valid, i.e. all executions of PRGB1 will match the plan PLANA01.

Another PLAN definition source is the IKJEFT01 PLAN (xxx) option.
The DB connection string lookup logic can also be customized programmatically, see custom plan mapping and Password plugin for more information.

4.11. Sysout Folder Naming Convention

The unique job folder under the sysoutFolderPath can be configured by editing the sysoutFolderNamingPattern option in the catalog configuration. Two components have a specific meaning: ID and NAME. The ID string is replaced with the unique job ID, while the NAME string is replaced with the job name. The ID string is mandatory, whereas the NAME string is optional.

For Example:

 sysoutFolderNamingPattern="JOB{ID}.{NAME}"

When the job name is not yet known, such as when a job is submitted, but there are errors in parsing, the job name is set to UNKNOWN. Once the job name is known, the sysout folder will be renamed accordingly.

This directory contains different files and directories:

  • JCLListing.JCL: The listing of JCL with all the included items resolved.

  • MSGLOG.txt: The messages displayed on the console.

  • PROCESS.txt: The list of processes executed by this job.

  • RETURNCODE.TXT: The return code of the job.

  • SYSLOG.<job name>.txt: The syslog of the job. Information about the job and its different steps.

  • SerializedJob.json: Raincode internal usage for restart.

For each PROC/STEP, there is a directory containing the files generated by the job, e.g. SYSOUT, SYSPRINT. These files are only present if they are not empty.

4.12. SDSN wait

Specifies the installation policy for batch jobs that must wait to enqueue the dataset (Locking). Possible values are NO, YES, 1-999999 with a default of 3600 seconds (one hour)

Specifies whether to cancel jobs that must wait to enqueue the dataset:

  • NO: The system cancels the job, releases resources, and issues the message RC904.

  • YES: When YES is specified, and a batch job’s enqueue request cannot be satisfied, it will wait forever until it gets the resource

  • 1-999999: A timeout value in seconds to wait. If the enqueue request cannot be satisfied in the defined time, the system cancels the job and issues message RC904.

Use caution when specifying YES or a timeout, as this can cause deadlocks with other jobs in the system.

4.13. SMS Configuration

The Storage Management Subsystem (SMS) allows for the creation of templates with predefined data configurations by system programmers. Datasets can then be attached to such templates rather than repeating all the parameters file after file. SMS saves time and effort and, even more importantly, allows for a centralized and more abstract management of file properties.

Raincode’s JCL Emulator supports for SMS through two DD parameters, namely DATACLAS (Data Class) and STORCLAS (Storage Class). These parameters are specified in a configuration file. The default path of the configuration file is C:\ProgramData\Raincode\Batch\SMSConfig.txt.

A typical example of the contents of the configuration file:

DATACLAS:DSCLAS01=RECFM=FBA,LRECL=132,BLKSIZE=900
STORCLAS:SCLAS01=VOL=SER=VOL1
DATACLAS:DSCLAS02=DCB=(RECFM=FB,LRECL=120,BLKSIZE=2000)
STORCLAS:SCLAS02=VOL=SER=DEFAULT

The configuration file’s default location can be overidden using a smsConfigFilePath attribute in the Raincode.Catalog.xml.

For more details, please refer to the section Default catalog configuration. When Submit executes, it first checks for SMSConfig.txt at the location specified in the catalog. If it is not found, it checks at the default location to fetch the values for both classes.

4.14. Substvar

The JCL parser supports substituting variables that start with the # @ characters (e.g., # @VAR1). The values for these variables are stored in an XML file specified in the catalog configuration attribute substitutionVariableFilePath. The format of the file is given in the example below:

<Substvars>
  <Variable Name="# @MYVAR" Value="VAL1"/>
  <Variable Name="# @TEST" Value="HELLO"/>
</Substvars>

Variables can also be passed through the IJCLPreprocessor interface when the UpdateSubstvarVariables method is called. It is simply a dictionary of key/value pairs.

4.15. Setting up File Shares and UNC path locations

Setting up a file share and accessing it with its UNC path means having a centralized file share location, allowing a multi-batch server environment. Each batch server will access volumes and their datasets via the respective UNC path.

To enable this, first, share the folder on the server and note the remote path to the share. Then, modify the catalog configuration file to use the new share (for sysout, volumes, etc.) using the remote path.

4.16. Unit and Volume Configuration

Units are simply a named collection of volumes. The default unit is SYSDA.

Table 16. Unit Attributes

Attribute

Default Value

Description

name

Name of the default unit

isDefault

FALSE

The unit is the default unit

Volumes map to drives or folders on disk. They can be UNC shares or local folders.

In a distributed environment, the volumes should reside on a UNC share.
Table 17. Volume Attributes

Attribute

Default Value

Description

name

Name of the volume.

path

Folder that contains the data of the volume. It can be omitted if the catalogFormat is db and all the data are mapped to VSAMSql.

isDefault

FALSE

Is it the default volume.

To add new volumes to the catalog configuration, manually create a new folder on disk and add a new <Volume> element (under the <Volumes> element) with the path to the newly created folder.

4.17. Accessing catalog from a Linux Machine Using SMB

The Raincode catalog (Catalog.Configuration.xml) stored on a linux machine can be accessed remotely through two common file-sharing protocols:

  • NFS (Network File System)

  • SMB (Server Message Block)

This section focuses on guiding you through the process of accessing the Raincode catalog on a Linux machine using the SMB protocol.

By setting up an SMB file share, the Catalog.Configuration.xml file can be accessed and managed from a Windows environment, leveraging tools like Catalog Explorer and Record Editor without direct Linux support.

4.17.1. Creating and configuring SMB File share

In Azure:

  • Create a new Storage Account

  • Set up a File Share using the SMB protocol

    • Navigate to Storage Browser→ File shares

    • Click Add file share

smbprotocol
Figure 16. SMB protocol

Mount SMB File Share on Windows:

  • Right click on the file share and select Connect.

  • Under the Windows tab, choose a network drive letter (e.g., U: Drive) to mount the SMB share.

mounttodrive
Figure 17. Mount to drive
  • Copy the Azure connection script.

connectionscript
Figure 18. Connection script
  • Run the script in PowerShell to mount the SMB share as a network drive.

powershellscript
Figure 19. Execute script in PowerShell
  • The mounted network drive will now be visible in Windows File Explorer.

Udrive
Figure 20. Network drive in File Explorer

4.17.2. Mount SMB File Share on Linux

  • In Azure, select the Linux tab and copy the connection script.

connectionscript1
Figure 21. Connection script
  • Run the script on your Linux machine to mount the SMB share.

powershellscript1
Figure 22. Execute script on Linux

4.17.3. Integrating Linux Catalog with SMB Share

  • Place your Raincode.catalog.xml to the mounted SMB file share and ensure the DefaultVolume path in the configuration points to the SMB file share for Windows accessibility.

catconf
Figure 23. Catalog.Configuration.xml
  • Run the JCL using the Submit command with the Catalog Configuration parameter to reference the Raincode.Catalog.xml from the SMB share.

executejcl
Figure 24. Execute JCL

4.17.4. Accessing Linux Catalog on Windows

  • Open the mounted U: drive in the Windows File Explorer to view folders and files created after executing the JCL.

mountedw
Figure 25. Mounted SMB file share
  • Launch Catalog Explorer on Windows and point it to the mounted SMB share (e.g., U:\raincode\Batch) using File→ Change Configuration.

pointtoconfiguration
Figure 26. Point Catalog Explorer to the Raincode.Catalog.xml
  • You can access catalog content directly through the Catalog Explorer.

filecontent
Figure 27. File content in the catalog explorer
  • Double-clicking the file (e.g., SUBSTR.SORTED.FILE) will open it in the Record Editor for editing.

recordeditorcontent
Figure 28. Content in Record Editor

4.18. Use XML include in Raincode.Catalog.xml

Using <environmentVariables> or <programDBConnectionDefinitions> entities in the catalog configuration file may make this file large and unwieldy. So, store that information in separate files, possibly with different access permissions. This is possible since the catalog manager implements the W3C XML Inclusions (XInclude) 1.0 Recommendation for XML inclusion.

To allow this, the catalogConfiguration element needs to contain a xmlns:xi="http://www.w3.org/2003/XInclude" attribute. Inclusion of a file is then done by using an xi:include element, e.g. <xi:include href="file name" />.

xmlns:xi="http://www.w3.org/2003/XInclude" is a hardcoded signature that is recognized by the catalog manager. Even though it refers to a URL, your system does not need to be connected to the internet, there will be no connection to download anything. This signature is used simply to conform to the w3.org standard.

Sample usage of XML Include

File: Raincode.Catalog.xml

<catalogConfiguration
 xmlns:xi="http://www.w3.org/2003/XInclude"

><xi:include href="./envvars.xml" />
</catalogConfiguration>

File: envvar.xml

  <environmentVariables>
    <envvar name="Test1" stepId="STEP1.*">Test1Value</envvar>
    <envvar name="Test2" pgm="PRGB1">Test2Value</envvar>
    <envvar name="Test3" pgm="PRGA.*">Test3PRGA</envvar>
    <envvar name="Test3" >Test3OTHER</envvar>
  </environmentVariables>

The file envvar.xml will be included, and the actual configuration used will be equivalent to the following:

<catalogConfiguration
 xmlns:xi="http://www.w3.org/2003/XInclude"

><environmentVariables>
    <envvar name="Test1" stepId="STEP1.*">Test1Value</envvar>
    <envvar name="Test2" pgm="PRGB1">Test2Value</envvar>
    <envvar name="Test3" pgm="PRGA.*">Test3PRGA</envvar>
    <envvar name="Test3" >Test3OTHER</envvar>
  </environmentVariables>
</catalogConfiguration>

4.19. Customizing Legacy Runner calls

The catalog configuration has two means to customize the calling of the legacy runner:

  • Instead of the default runner, a user-defined runner can be specified

  • Whenever a runner is called, additional arguments can be added to the list of arguments.

The former is done through the legacyRunner entity, e.g., as follows:

<legacyRunner>
  <runner>/opt/bin/rcrunner1</runner>
</legacyRunner>

The latter is done through the legacyRunnerParameters entity, e.g., as follows:

<legacyRunnerParameters>
  <param>-PluginPath=C:\plugins\</param>
  <param>-Plugin=passwordRewriter.dll</param>
</legacyRunnerParameters>

Both of the above can be further fine-tuned. Following the same pattern as environment variable definitions, different runner and parameter values for specific steps or programs can be defined. For example, we can run a different runner on specific program calls or JCL steps, and enable Trace level logging whenever a certain program will be called:

<legacyRunner>
  <runner prg="MYPROG" >/opt/bin/rcrunner1</runner>
  <runner step="STEP001" >/opt/bin/rcrunner1</runner>
</legacyRunner>
<legacyRunnerParameters>
  <param pgm="SPPROG">-LogLevel=Trace</param>
</legacyRunnerParameters>

5. Utilities

Raincode JCL provides several utility programs that emulate the functionality of their mainframe counterparts, such as the IDCAMS file manipulation utility. All these programs are located in the installation directory, where Submit.exe is also found and they have the same name as their mainframe counterpart to ensure seamless treatment of JCLs. This chapter presents the details of several utilities provided by Raincode JCL.

5.1. Implemented JCL Utilities

Table 18. Implemented JCL Utilities

Utility name

Aliases

Description

ScanOnly mode

Run in-process

BPXCOPY

Copies a dataset into file(s)

Yes

Yes

CPY2PDS

Copies a file into a PDS

No

Yes

DFSRRC00

IMS Region controller - Provides access to the IMS BMP to the database

Yes

Yes

DSNTEP2

DSNTEP2TSQL

Executes dynamic SQL statements

No

Yes

DSNTIAUL

DSNTIADTSQL, DSNTIAUD, DSNTIAULDB2, DSNTIAULTSQL

Unloads data from DB2 tables into sequential datasets

No

Yes

DSNUTILB

DSNUTILBSQL, INZUTILB

Handles DB2 commands from a JCL

Yes

Yes

EZTPA00

Loads and executes an easyTrieve program

Yes

Yes

FILEAID

Provides file and data processing capabilities

Yes

Yes

FILEBKUP

Provides dataset backup and restore capabilities using ZIP archives

Yes

No

ICETOOL

Performs multiple operations on one or more datasets in a single step, using the capabilities of DFSORT

Yes

Yes

IDCAMS

Access Method Services Program that provides file manipulation, including creation, modification, and deletion of datasets

Yes

Yes

IEBCOPY

Copies and merges partitioned datasets

Yes

Yes

IEBGENER

ICEGENER

Copies sequential datasets or converts sequential datasets to PDS

No

Yes

IEFBR14

Implements a no-op operation as a separate process

No

Yes

IKJEFT01

IKJEFT01A, IKJEFT1A, IKJEFT1B

Executes TSO commands in a batch job

Yes

Yes

ISRSUPC

SUPERC

Compares datasets and performs dataset searches

Yes

Yes

RCFTP

FTP, SFTP

Provides FTP (a mainframe-compatible FTP implementation) and SFTP (an implementation with similar syntax)

No

No

SETLABEL

Sets a label to a given dataset

No

Yes

SORT

ICEMAN

DFSORT implementation

Yes

Yes

ZIP390

File archiving and Email sending

Yes

No

5.2. IDCAMS

IDCAMS (Integrated Data Cluster Access Method Services) is a file manipulation utility. It allows for the creation, modification, and deletion of datasets.

5.2.1. General Assumptions

Standard IDCAMS entry name specifications are used. Lowercase characters are converted to uppercase. Invalid characters outside of the 0-255 range are silently ignored.

Windows-reserved file names CON, PRN, AUX, NUL, COM[1-9], and LPT[1-9] cannot be used as a dataset name qualifier.

5.2.2. Additional command line arguments

The following command-line arguments have been added to the Raincode implementation:

  • ScanOnly: performs only scanning/parsing of passed input

  • PreProcessDump: dumps preprocessed input to a file

  • ScanToDb: works in pair with ScanOnly to dump information about the statements after parsing by creating a database table of statements, their parameters, and the indication of a successful parsing.

5.2.3. Modal commands

IF-THEN-ELSE, NULL, DO-END, SET, and CANCEL modal commands are supported.

5.2.4. Supported functional commands

Commands are listed in the unabbreviated form. Standard IDCAMS abbreviations can be used.

Allocate datasets
ALLOCATE DATASET (dsname)
[FILE(ddname)]
[NEW|OLD|SHR|MOD]
[KEEP|CATALOG|DELETE|UNCATALOG]
[DIR(integer)]

Allocates dataset dsname.

DIR must be specified for a new partitioned dataset.

This command is only useful for allocating a new partitioned dataset.

Some of the parameters file(ddname), old, shr, mod, keep, delete, uncatalog are supported by the parser but are currently ignored.
Rename
ALTER entryname NEWNAME(newname)

Rename entryname to newname.

Define alias
DEFINE ALIAS (NAME(aliasname) RELATE(entryname))
At this time, the DEFINE ALIAS command is recognized but ignored.
Define Cluster

Defines a VSAM cluster. Supported attributes are NAME, DATA, INDEX, RECORDSIZE, KEYS, ERASE/NOERASE, INDEX, CYLINDERS, KILOBYTES, MEGABYTES, RECORDS, TRACKS, ALTERNATEINDEX. Only KSDS indexed files are supported at the moment.

Implementation of the VSAM KSDS for DEFINE ALTERNATEINDEX has a few limitations, as mentioned below:

  • The definition ALTERNATEINDEX must be done before any actual creation of the datafile (open output and add record)

  • The attributes used by DEFINE ATLERNATEINDEX are KEY and UNIQUE/NOUNIQUE. All other attributes are ignored

  • Added ALTERNATEINDEX are always UPDATE

  • DELETE of ALTERNATEINDEX is not supported

  • BLDINDEX is not supported, as ALTERNATEINDEX are always updated

Define GDG (Generation Data Group)
DEFINEGENERATIONDATAGROUP|GDG
      (NAME(entryname)
       [ LIMIT(limit)]
       [SCRATCH | NOSCRATCH]
       [EMPTY|NOEMPTY]
      )

Define a GDG (Generation Data Group).

Delete datasets or GDG (Generation Data Group)
DELETE (entryname[ entryname …])
[ALIAS|
ALTERNATEINDEX|
CLUSTER|
GENERATIONDATAGROUP|
LIBRARYENTRY|
NONVSAM|
NVR|
PAGESPACE|
PATH|
TRUENAME|
USERCATALOG|
VOLUMEENTRY|
VVR]
[ERASE|NOERASE]
[FILE(ddname)]
[FORCE|NOFORCE]
[PURGE|NOPURGE]
[RECOVERY|NORECOVERY]
[SCRATCH|NOSCRATCH]

Deletes a dataset or a GDG.

Wildcards are supported in the entryname.

Partial datasets are deleted only if they contain no members.

Some of the parameters like alias, cluster, libraryentry, nvr, pagespace, path, truename, usercatalog, volumeentry, vvr, recovery, norecovery, scratch, noscratch are supported by parser but currently ignored.
List catalog entries
LISTCAT ENTRIES(entryname [ entryname...])|LEVEL(level)
[USERCATALOG]
[NONVSAM]
[OUTFILE(ddname)]
[NAME|HISTORY|VOLUME| ALLOCATION|ALL]

List catalog entries. Listing non-VSAM datasets option is supported. Wildcards are supported in the entryname. Listing to an output file is supported.

Some of the parameters usercatalog, history, volume, allocation, are supported by the parser but are currently ignored.
Print
PRINT {INFILE(ddname)|INDATASET(entryname)} [COUNT(number)]
[CHARACTER|HEX|DUMP]
[OUTFILE(ddname)]

Printing in hex/dump or character formats is supported - print dataset as text records. Only sequential datasets are supported. Printing to an output file is supported.

Copy
REPRO {INFILE(ddname)|INDATASET(entryname)}
{OUTFILE(ddname)|OUTDATASET(entryname)}
[SKIP(number)]
[COUNT(number)]

Copy dataset to a new dataset. Only sequential datasets are supported.

5.3. IEBGENER

IEBGENER is a copy utility that copies records from a sequential dataset or converts a dataset from a sequential organization to a partitioned organization.

There are four main use cases for IEBGENER:

  1. Creating a copy without editing - creates an identical copy of the source dataset.

  2. Creating a copy with editing - creates an edited copy of the source dataset by affecting the length, size, and organization of source records.

  3. Creating a partitioned dataset or PDS member without editing - creates the partitioned dataset and/or creates PDS members identical to the source dataset.

  4. Creating a partitioned dataset or PDS member with editing - creates the partitioned dataset and/or PDS members from the source dataset by affecting source records' length, size, and organization.

The last use case, creating a partitioned dataset or PDS member with editing, is currently unsupported.

5.3.1. General Assumptions

When creating a PDS member, the PDS directory needs to exist (see the chapter on mainframe file system emulation), or the DD=SYSUT2 data definition needs to contain information that the dataset is partitioned.

5.3.2. Utility control statements

There are five utility control statements: GENERATE, MEMBER, RECORD, EXITS and LABELS. Of these, EXITS and LABELS are not supported

GENERATE

The GENERATE statement is required when output needs to be partitioned, or editing is to be performed.

The GENERATE statement needs to be the first statement in the instream-data content.
[label] GENERATE    [,MAXNAME=n]
                    [,MAXFLDS=n]
                    [,MAXGPS=n]
                    [,MAXLITS=n]
                    [,DBCS={YES|NO}]

All GENERATE statement parameters are supported by the parser; however, only MAXNAME and MAXFLDS parameters have their functionality implemented.

MEMBER

The MEMBER statement is used when the output dataset needs to be partitioned.

[label] MEMBER NAME=(name)
RECORD

The RECORD statement is used to define a record group and to supply editing information.

If the RECORD statement appears after the MEMBER statement, it defines editing information for that member, such as creating a PDS dataset (or PDS member) with editing.

If the RECORD statement appears just after the GENERATE statement, no MEMBER statements are allowed. When doing this, the RECORD statement defines editing information for the use case such as creating a copy with editing.

[label] RECORD  [{IDENT|IDENTG}=(length,'name',input-location)]
                [,FIELD=([length],
                        [{input-location|'literal'}],
                        [conversion],
                        [output-location])]
                [,FIELD=...]
                [,LABELS=n]

The parser supports all RECORD statement parameters. However, only the FIELD parameter has its functionality implemented, with the exception of its literal and conversion options.

Record groups and labels are currently unsupported.

5.4. Sort Runner

Raincode Sort Runner is designed for compatibility with the existing mainframe SORT utility; there is no change needed to the sort commands. It sorts, copies and merges datasets as it does on the mainframe.

The Sort Runner implements sort functionality for both SORT calls from COBOL or PL/I program and standalone SORT executions from a JCL. Its code resides in a .dll, which the Raincode runtime utilizes for all sort operations initiated from COBOL or PL/I. SORT.exe, also relies on this .dll to perform its work.

5.5. IKJEFT01

Raincode provides a bare-bone implementation of the IKJEFT01 utility. Only the following commands are partially implemented: RUN, OCOPY, and LISTCAT.

IKJEFT01 on the mainframe is often used to launch applications and connect them to the database. The Raincode implementation of IKJEFT01 relies on an underlying runner, which by default is rclrun.exe.

IKJEFT01.exe will invoke rclrun.exe and pass the required command-line arguments. To use an alternative implementation of a runner, configure it by adding an environment variable LegacyRunner and providing the full path to the executable of the alternative runner.

To provide connection strings to the utility, the user must provide an environment variable RC_DB_FILE containing the path to a file providing the connection strings. This file must be in the following format:

  • One connection string per line

  • Each line consists of three comma-separated parameters: <System>, <DB Type>, <Connection String>

Supported values for DBType are SqlServer and DB2.

For more information on database connections and connection strings, refer to the section JCL connection string retrieval.

To debug a program launch by IKJEFTK01, add the parameter -DEBUG.

For example:

//STEP002  EXEC PGM=IKJEFT01,PARM='-DEBUG'

5.6. DSNUTILB

Raincode provides an implementation of the DSNUTILB load and unload functionality. It obtains the connection string from the environment variables RC_DB_CONNECTION and RC_DB_TYPE. Both are set up by the JCL interpreter when the DSN parameter is provided to the EXEC command. For more details on how to specify the database to be used, refer to the section JCL connection string retrieval.

By default, DSNUTILB executes the SQL queries without any modification. However, in some cases, for example, when the target DB type changes, it is desirable to rewrite the queries before executing them. For more details, refer to the Query rewriting section.

The utility understands UNLOAD commands of the following form:

UNLOAD TABLESPACE spacename FROM TABLE tablename LIMIT amount
       WHEN condition

And LOAD statements of the form:

LOAD DATA RESUME YES INDDN name
INTO TABLE tablename WHEN condition (columndescription, *)

To load data, DSNUTILB uses either inserts or bulk inserts, depending on the UseBulk option. Bulk inserts are supported only for the SQL Server. The number of rows sent together to the database is defined by the LoadBufferSize option.

If the SYSDISK option is enabled and an error occurs during the insertion, the tool retries with a buffer 100 times smaller. This process continues until the specific row causing the issue is identified.

5.6.1. Command line options for DSNUTILB

The following are the command line options available for DSNUTILB

General
Table 19. Details of command-line options for DSNUTILB in category General
Command-line option Default value Description

BulkLoadTimeout

Wait time (in seconds) before terminating the attempt to execute the command and generating an error. If not set use the C# default

CatalogConfiguration

Path to the configuration file for the catalog.

Comment

User define comment pass as argument

Debug

Causes a JIT breakpoint to be hit. Useful for debugging custom hooks.

KeepTempFiles

Retain temporary files on disk instead of deleting them (default behavior)

LoadReplaceSqlCommand

delete

Command to use to clean-up the existing records during LOAD REPLACE, default is DELETE. Valid values are:

  • DELETE

  • TRUNCATE

LogToConsole

Registers a log file listener that outputs to the console

ScanInventory

The repository inventory file name to proceed

ScanOnly

Indication that input should only be parsed

Load
Table 20. Details of command-line options for DSNUTILB in category Load
Command-line option Description

LoadBufferSize

The size of the buffer used by the load. I.e. the number of lines inserted together. The default value is 500 for insert and 500000 for bulk insert (see UseBulk)

UseBulk

Load uses bulk insert. Only supported by SQL Server. True by default for SQL Server

Miscellaneous
Table 21. Details of command-line options for DSNUTILB in category Miscellaneous
Command-line option Default value Description

DotNetConfigFile

This command-line option is an additional .net 'app.config' file.

Help

Displays the tool’s help information.

IgnoreUnkownArgs

Info

False

Displays a description of the program.

LogLevel

INFO

Specifies the log level. Valid values are:

  • SILENT

  • ERROR

  • WARNING

  • PROGRAM_OUTPUT

  • PROGRAM

  • INFO

  • DEBUG

  • TRACE

  • DIAGNOSTIC

Version

False

Displays the version information.

Plugin
Table 22. Details of command-line options for DSNUTILB in category Plugin
Command-line option Description

Plugin

The list of plugins to be loaded when the tool executes.

PluginPath

This command-line option specifies the path to plugins that are searched.

5.7. DSNTIAUL

Raincode provides an implementation of the DSNTIAUL utility. It obtains the connection string from the environment variables RC_DB_CONNECTION and RC_DB_TYPE. Both are set up by the JCL interpreter when the DSN parameter is provided to the EXEC command. For more details on how to specify the database to be used, refer to the section JCL connection string retrieval.

By default, DSNTIAUL executes the SQL queries without any modification. However, in some cases, for example, when the target DB type changes, it is desirable to rewrite the queries before executing them. For more details, refer to the Query rewriting section.

5.8. DSNTEP2

Raincode provides an implementation of the DSNTEP2 utility. It obtains the connection string from the environment variables RC_DB_CONNECTION and RC_DB_TYPE. Both are set up by the JCL interpreter when the DSN parameter is provided to the EXEC command. For more details on how to specify the database to be used, refer to the section JCL connection string retrieval.

By default, DSNTEP2 executes the SQL queries without any modification. However, in some cases, for example, when the target DB type changes, it is desirable to rewrite the queries before executing them. For more details, refer to the Query rewriting section.

5.9. DFSRRC00

DFSRRC00 is the utility to access IMS through a JCL. Raincode only implements a subset of the original utility:

  • BMP/DLI: execute a program that uses IMS

  • ULU: load/unload data

DFSRRC00 takes only one argument: the PARM taken from the JCL. Recall that on the mainframe this PARM consists of a comma-separated list of elements. The length of the list and the meaning of the elements depend on the value of the first element of the list.

Further, this document details what subset of DFSRRC00 is implemented.

5.9.1. BMP/DLI

If the first element of the parameter list is BMP or DLI, the program executes a batch program (COBOL or PL/I). The list of parameters is 21 elements long; but only a subset of these is supported, as outlined in the table below.

Table 23. Supported parameters in DFSRRCC00 BMP and DLI
List position Name or value Description

1

BMP or DLI

Execution mode

2

MBR

Specify the name of the program

3

PSB

Specify PSB name

19

CKPTID

Specify checkpoint for program restart

20

IMSID

Override IMS subsystem identifier

21

DEBUG

Set this parameter to TRUE to debug the IMSql plugin

In Raincode IMSql, IMSID is the plan used to connect to the database. If the execution mode is BMP, IMSID is the region name, and the plan config_<IMSID> is used to get the connection string to the TM database.

5.9.2. ULU

If the first element of the parameter is ULU, the utility unloads or loads a DBD depending on the value of the second element: DFSURGU0 to unload or DFSURGL0 to load.

Table 24. Supported parameters in DFSRRCC00 ULU

List Position

Value

Description

1

ULU

2

DFSURGU0 or DFSURGL0

Unload or load

3

The DBD name

The name of the DBD to unload/load is in the third position. When loading, the DFSUINPT DD is the dataset that will be loaded into the DBD. When unloading, the DFSURGU1 is the dataset in which the DBD will be unloaded. To get the connection to the database, the prefix (until the last .) of the IMS DSN is used as a key to search in the JCL connection string retrieval specification.

5.10. FTP

Raincode provides an implementation for the mainframe FTP functionality. It accepts both FTP and FTPS protocols. If FTPS is used, all certificates are accepted.

The connection information is read from the NETRC DD. The environment variable USERID contains the default user id that is used to find FTP.DATA

5.10.1. Implemented options and commands

The utility has support for two options: Exit and TRACe. The list of implemented commands is given in the table below.

Table 25. Supported commands in FTP

Command

Notes

APpend

AScii

Uses the encoding defined in the defaultAsciiCodePage property of the catalog configuration. For more details, refer to Catalog configuration.

BINary

BLock

CWd

CD

CDUp

CLose

DELEte

DIr

EBcdic

Uses the encoding defined in the defaultEbcdicCodePage property of the catalog configuration. For more details, refer to Catalog configuration.

FIle

Get

Not for VSAMSql

LCd

LS

MDelete

MGet

MKdir

MOde

Only B and S mode are supported

MPut

NOop

Open

PAss

PUt

PWd

QUIt

RECord

REName

RMdir

STREam

STRuctu

Only F and R are supported

TYpe

Only A and E are supported

User

Verbos

5.10.2. Command line options for FTP

Below are the details of the FTP command line options, as generated by ftp.exe.

General
Table 26. Details of command-line options for RCFTP in category General
Command-line option Description

CatalogConfiguration

Path to the configuration file for the catalog.

Comment

User define comment pass as argument

Debug

Causes a JIT breakpoint to be hit. Useful for debugging custom hooks.

f

Path to FTP.DATA config file.

KeepTempFiles

Retain temporary files on disk instead of deleting them (default behavior)

LogToConsole

Registers a log file listener that outputs to the console

ScanInventory

The repository inventory file name to proceed

ScanOnly

Indication that input should only be parsed

t

Ftp timeout in second (default is 15).

Miscellaneous
Table 27. Details of command-line options for RCFTP in category Miscellaneous
Command-line option Default value Description

DotNetConfigFile

This command-line option is an additional .net 'app.config' file.

Help

Displays the tool’s help information.

IgnoreUnkownArgs

Info

False

Displays a description of the program.

LogLevel

INFO

Specifies the log level. Valid values are:

  • SILENT

  • ERROR

  • WARNING

  • PROGRAM_OUTPUT

  • PROGRAM

  • INFO

  • DEBUG

  • TRACE

  • DIAGNOSTIC

Version

False

Displays the version information.

Plugin
Table 28. Details of command-line options for RCFTP in category Plugin
Command-line option Description

Plugin

The list of plugins to be loaded when the tool executes.

PluginPath

This command-line option specifies the path to plugins that are searched.

Sftp
Table 29. Details of command-line options for RCFTP in category Sftp
Command-line option Description

hostkey

hostkey for machine connecting to for Sftp.

keyfile

Path to Open SSH (PEM) certificate file for Sftp.

keypcn

Path to Open SSH (PEM) certificate file for Sftp. (alias of keyfile)

passkey

PassKey for ppk certificate file for Sftp.

sftp

Use Sftp.

5.11. SFTP

Secure File Transfer Protocol (SFTP) replaces FTP, utilising Secure Shell (SSH) protocol version 2.0 to ensure safe file transfers. While it supports the same command structure as FTP, SFTP includes extensions that enable various types of authentication methods, as mentioned below:

Authentication Methods:

  • Username and Password

    • Users sign in with their usual username and password.

  • Public/Private Key (Certificate-based authentication)

    • This method requires OpenSSH keys:

      • The private key is stored on the FTP server

      • The public key is provided as a parameter to the SFTP command

  • Certificate plus a Passphrase

    • This method works like key-based authentication, but adds a Passphrase for more security.

Configuration Using DD Statements:

The authentication method is specified using specific DD names, as mentioned below:

  • ENVVAR DD

    • This dataset contains the values of two variables:

      • CLIENT (alias MFFTP_CLIENT): Specifies whether the client type is FTP or SFTP

      • SFTP_AUTH (alias MFFTP_SFTP_AUTH): Specifies which authentication method to be used

  • SFTPAUTH DD Statement

    • Contains the required authentication details

    • The parameters vary depending on the value of SFTP_AUTH

  • SFTPPPK

    • The private key is used for authentication.

5.11.1. SFTPAUTH DD Statement - Format and supported commands

The SFTPAUTH DD statement provides optional input data used by Raincode FTP (RCFTP) for SFTP configuration and authentication. It is read as a line-oriented text dataset and can include both FTP/SFTP parameter commands and authentication entries in .netrc file format.

The file is interpreted based on the processing logic’s context.

Dataset definition

Below is an example JCL for a dataset definition.

//SFTPAUTH DD DSN=your.dataset.name,DISP=SHR

Supported dataset types are:

  • Sequential dataset

  • In-stream data

General Format Rules
  • One instruction per line

  • Empty lines are ignored

  • Lines may be truncated at column 72 when defined in-stream

  • Inline comments are supported using ;

Example for inline comments:

SFTP_AUTH 3 ; user/password authentication

In the above example, user/password authentication is treated as a comment.

SFTP Mode Activation

To enable SFTP mode, use one of the following:

CLIENT SFTP

or

MFFTP_CLIENT SFTP

Supported Parameter Commands

Each parameter follows one of these formats:

KEYWORD value

or

KEYWORD = value

Supported Keywords

The following keywords are supported:

  • PASVTYPE

  • INACTTIME

  • MFFTP_OUTPUT_LRECL

  • LRECL

  • RECFM

  • VOLUME

  • SBSENDEOL

  • SBDATACONN

  • CLIENTEXIT

  • MFFTP_CLIENT

  • CLIENT

  • SFTP_AUTH

  • MFFTP_SFTP_AUTH

SFTP Authentication Flags

The keyword: SFTP_AUTH <value> defines the authentication method.

SFTP_AUTH Values (Bitmask)

Value Meaning

  • 1 = User ID

  • 2 = Password

  • 4 = Certificate / Private Key

  • 8 = Passphrase

Common Combinations

Value Meaning

  • 3 = User + Password

  • 5 = User + Key

Value Meaning

  • 12 = Certificate + Passphrase

  • 13 = User + Key + Passphrase

If value is not specified then by default SFTP_AUTH will use 3 (User + Password)
Authentication Entries (.netrc - like format)

The dataset also supports authentication entries similar to .netrc.

Supported tokens

  • machine

  • login

  • user

  • password

  • pass

Examples

  • machine sftp.server.com login myuser password mypass

  • machine sftp.server.com user myuser pass mypass

Key-Based Authentication Entries

Additional tokens are supported for key-based authentication:

  • keypcn or keyfile - loads the private key from the specified path at runtime

  • keypass - provides the key Passphrase

  • hostkey - enables host verification

Example

  • keypcn: C:\keys\id_rsa

  • keypass: myPassphrase

  • hostkey: ssh-ed25519 AAAAB3…​

Constraints
  • Only the OpenSSH private key format is supported

  • PuTTY .ppk format is not supported

  • Key file content is loaded at runtime.

Processing Behavior

The SFTPAUTH dataset is processed in two stages:

  • Parameter parsing (FTP/SFTP configuration)

  • Authentication extraction (.netrc style parsing)

Examples

Example 1: Key-Based Authentication

//STEP6    EXEC  PGM=FTP,
//         PARM='FTP.MYORG.COM'
//ENVVAR   DD *
CLIENT=sftp
SFTP_AUTH 13
/*
//SFTPAUTH DD *
machine ftp.myorg.com user ftptest
keypcn C:\keys\id_rsa
keypass mySecretPassphrase
/*
//INPUT    DD *

Example 2: SFTP with a username and password

//STEP5    EXEC  PGM=FTP,
//         PARM='FTP.MYORG.COM'
//ENVVAR   DD *
 CLIENT=sftp
 SFTP_AUTH=3
/*
//SFTPAUTH DD *
 machine ftp.myorg.com user ftptest pass Xxxx
/*
//INPUT    DD *
 CD /home
 PUT 'MY.DATA.PUBKEY'
 QUIT
/*

Example 3: SFTP with a certificate and an OPEN command

//STEP6    EXEC  PGM=FTP
//ENVVAR   DD *
 CLIENT=sftp
 SFTP_AUTH=5
/*
//SFTPPPK  DD DSN=PRIV.KEY,DISP=(SHR)
//INPUT    DD *
 OPEN ftptest@ftp.myorg.com
 CD /home
 TIMEOUT 20
 PUT 'DATA.DATA1' SDATA1.txt
 GET SDATA1.txt 'DATA.DATA2'
 QUIT
/*

Example 4: SFTP with a certificate and SFTPAUTH and without an OPEN command

//STEP6    EXEC  PGM=FTP,
//         PARM='FTP.MYORG.COM'
//ENVVAR   DD *
 CLIENT=sftp
 SFTP_AUTH=5
/*
//SFTPAUTH DD *
 machine ftp.myorg.com user ftptest
/*
//SFTPPPK  DD DSN=PRIV.KEY,DISP=(SHR)
//INPUT    DD *
 CD /home
 TIMEOUT 20
 PUT 'DATA.DATA1' SDATA1.txt
 GET SDATA1.txt 'DATA.DATA2'
 QUIT
/*

Example 5: SFTP with a certificate and .netrc and without an OPEN command

//STEP6    EXEC  PGM=FTP,
//         PARM='FTP.MYORG.COM'
//ENVVAR   DD *
 CLIENT=sftp
 SFTP_AUTH=5
/*
//NETRC    DD DSN=SFTPTEST.NETRC,DISP=OLD
//SFTPPPK  DD DSN=PRIV.KEY,DISP=(SHR)
//INPUT    DD *
 CD /home
 TIMEOUT 20
 PUT 'DATA.DATA1' SDATA1.txt
 GET SDATA1.txt 'DATA.DATA2'
 QUIT
/*
With SFTPTEST.NETC containing:
machine ftp.myorg.com login ftptest

5.12. CompareFiles

Compares INFILE and OUTFILE DD. If the files are different, the return code is 16. Otherwise, it is 0.

PARM:

  • SKIP = n - skip the first n lines of INFILE

  • COUNT = n - compare only n lines

  • RECORD - if set, LSEQ files are compared as binary files; otherwise they are compared as a text file.

Example:

//PASO020  EXEC PGM=CompareFiles,PARM='SKIP=1'
//OUTFILE   DD DSN=K14998.DATA.GROUP1,DISP=SHR
//INFILE    DD DSN=K14998.DATA.RESULT,DISP=SHR
//*

5.13. File-AID

Raincode supports a subset of the batch capability included in BMC’s File-AID utility, which is widely used for file and data handling in mainframe systems. File-AID is offered as a program that can be executed by a job step in Batch. In that case, the SYSIN can contain multiple File-AID statements, which all consist of the following three things:

  • A DD name which refers to a dataset

  • The function to perform on the dataset

  • A list of optional parameters to manipulate records

Example:

//JOBNAME JOB JOB CARD INFORMATION
//STEP1 EXEC PGM=FILEAID,REGION=8M
//DD01  DD *
Andy                 van Steenderen      2004-03-25  306 Lazy Timber
German               Brownlie            2001-08-25  596 Shady Pond
Angelo       N.F.J.  Fox                 1991-11-01  918 Old Avenue
Hugh         C.T.    Clay                2003-04-19  891 Lazy Trafficway
Jolie        W.      Denhartog           2006-03-08  P.O. Box 17564
Garret               Hartog              1969-12-07  125 Cinder Viaduct
/*
//DD01O    DD DSN=MY.TEST.FILE,
//        DISP=(NEW,CATLG,DELETE),RECFM=LSEQ,VOL=SER=DEFAULT,LRECL=80
//SYSIN DD *
  $$DD01 COPY IF=(1,EQ,C'A,H')
/*

In the above example, DD01 is an instream dataset containing some dummy data. File-AID is used to copy records from DD01 to DD01O. The parameter IF limits the copied records to those that have the character A or H at the first position. Therefore, MY.TEST.FILE will contain the following:

Andy                 van Steenderen      2004-03-25  306 Lazy Timber
Angelo       N.F.J.  Fox                 1991-11-01  918 Old Avenue
Hugh         C.T.    Clay                2003-04-19  891 Lazy Trafficway

5.13.1. Implemented functions and parameters

Raincode’s implementation of this utility can parse all valid File-AID programs but only implements a subset, detailed as the functions and parameters listed in the tables below. You can also check for the specific support of any File-AID command automatically by using the -ScanOnly flag together with the Submit command, which will trigger a check for validity (without actually executing the JCL). When this option is used, the RC_UTILITIES_PARSING_STATUS table in the repository will contain information about each statement in the program, and more specifically, an error message if a File-AID command requires functionality that is not yet supported by Raincode’s implementation.

Table 30. Supported functions in File-AID

Function

Notes

COPY

COPYBACK and COPYMEM are not yet supported

DROP

SPACE

SPACEBACK is not yet supported

UPDATE

USER

Table 31. Supported parameters in File-AID

Parameter

Notes

CEM

EDIT

EDITALL

FORM

Only supported for JCL

IF

IN

MAXENT

MEMBER

MEMBERS

MOVE

ORIF

OUT

PADCHAR

REPL

REPLALL

RLM

WRITE

5.14. SMTPMAIL

The SMTPMAIL utility allows sending emails directly from JCL using an SMTP mail host. The utility accesses the following environment variables in order to establish a connection and send an email.

  • SMTP_HOST: Specifies the SMTP host.

  • SMTP_USER: Specifies the SMTP username.

  • SMTP_PASSWORD: Specifies the SMTP password.

  • SMTP_FROM: - If set to an email address, this variable defines the sender’s email address. If no email address is specified, the utility will default to sending the email from the host of the originator using the format Jobname@localhost, where Jobname is the name of the current JCL job being executed.

The environment variables SMTP_USER and SMTP_PASSWORD are optional, depending on your SMTP server’s authentication requirements.

Below is a sample code snippet.

smptpmail
Figure 29. Sample

The utility processes the SMTPIN DD in the following steps:

  • It identifies the recipient email addresses (xyz@raincode.com and abc@raincode.com).

  • After detecting a new line or an empty line, it identifies the email’s subject (e.g., SMTPMAIL Utility nightbuild test - Text and CSV file attachments).

  • If there is a space following the subject line, and the keyword MIME-VERSION appears immediately after, the JCL interprets this as an indication that one or more attachments are included and need to be processed. Once MIME-VERSION is identified, the JCL examines the next line to determine the type and source of the attachment. This line must specify:

    • The attachment type, such as TXT, CSV, or other supported formats (e.g., CONTENT-TYPE: TEXT/PLAIN or CONTENT-TYPE: TEXT/CSV).

    • A DDNAME, for example, ATTACH01 (e.g., CONTENT-DDNAME : ATTACH01, FILENAME=TEST.TXT). This declaration indicates that the content pointed to by the specified DDNAME will be treated as an attachment. The content will be processed in text format, resulting in an attachment named accordingly (e.g., TEST.TXT).

    • This utility also allows you to specify an attachment’s character encoding. For example: CONTENT-DDNAME: ATTACH01, FILENAME=TEST.CSV; ENCODING=1252 sets the CSV file’s encoding to 1252. You can specify the encoding using either its numeric code or its name, and this applies only to the attachment encoding received by the email’s recipient, with no change made to the encoding of the JCL file (SMTPTEST.CSV.FILE).

  • After another new line or an empty line, the body of the email is identified (e.g., Please find attached file.).

The CONTENT-DDNAME must appear immediately after the CONTENT-TYPE in the same sequence; if not, the utility will fail to recognize the attachment.
Attachments are optional; if the attachment header metadata is not provided, the utility will still send the email containing only the subject and body.

This utility also allows you to explicitly specify the sender by using a FROM: identifier. Recipient addresses must be specified separately, either through a TO: identifier or by listing the addresses on recipient lines as shown in the examples below.

smtp1
Figure 30. Example showing FROM and TO identifier
Only one FROM: identifier can be used.
smtp2
Figure 31. Example showing a FROM identifier without a TO identifier
Although using the FROM: identifier is recommended for clarity, the utility can also operate without it.

You may also use aliases for both the sender and recipient addresses, as shown in the sample code. When aliases are included, the utility uses the text inside < > to determine the actual FROM and TO email addresses.

alias
Figure 32. Alias Example
Aliases must be applied to both the FROM and TO fields.

5.15. SUPERC

Raincode provides a subset of the SUPERC utility, which compares datasets in the Mainframe systems similarly to diff programs. SUPERC is offered as a program that can be executed by a job step in Batch. In that case, the SYSIN can contain multiple SUPERC statements, which consist of the following four elements:

  • A list of parameters to manipulate and filter datasets before and during comparison. This list also contains the kind of comparison applied (by file, line, word or byte) and the format of the output;

  • A DD name which refers to a first and presumably older version of a dataset;

  • A DD name which refers to a second and presumably more recent version of a dataset;

  • A DD name which refers to the dataset containing the comparison output, as a listing.

Example:

//PSTEP001 EXEC PGM=ISRSUPC,
//        PARM=(OVSUM,LINECMP,
//         '',
//         '')
//NEWDD    DD  DSN=FILE.INPUT1,DISP=SHR
//OLDDD    DD  DSN=FILE.INPUT2,DISP=SHR
//OUTDD    DD  DSN=FILE.OUTPUT,DISP=(,PASS),
//             DCB=(LRECL=133,BLKSIZE=23408,RECFM=FBA)

In the above example, OLDDD is a dataset compared to another NEWDD dataset. SUPERC compares these two datasets according to the options provided in the PARM field. When the LINECMP option is enabled, the datasets are compared line by line. In this example, OVSUM means that SUPERC will display comparison result in a summarised form (Overview summary) containing the types of differences (if any) between the datasets and their count. For instance, three matches and one insertion in the new dataset. This summary will be saved in FILE.OUTPUT.

If the OLDDD (FILE.INPUT2) file contains the following:

1000  	Brussels                      	192088
1010  	Admin City                    	7910
1020  	Laeken                        	37936

and the NEWDD (FILE.INPUT1) file contains the following:

1000  	Brussels                      	192088
1010  	Admin City                    	7910
1020  	Laeken                        	37936
1060  	St-Gilles                     	51660

then, FILE.OUTPUT will contain the following:

1 ISRSUPC   -    FILE/LINE/WORD/BYTE/SFOR COMPARE UTILITY-   21/05/2025 10:55:23 PAGE 1
 NEW: FILE.INPUT1                         OLD: FILE.INPUT2
 LINE COMPARE SUMMARY AND STATISTICS
 3 NUMBER OF LINE MATCHES                 0 TOTAL CHANGES(PAIRED+NONPAIR)
 0 REFORMATTED LINES                      0 PAIRED CHANGES(REFM + PAIRED)
 1 NEW FILE LINE INSERTIONS               1 NON - PAIRED INSERTS
 0 OLD FILE LINE DELETIONS                0 NON - PAIRED DELETES
 4 NEW FILE LINES PROCESSED
 3 OLD FILE LINES PROCESSED

5.15.1. Implemented functions and parameters

The product can parse SUPERC programs but only implements the parameters listed in the tables below. You can also check support for your program automatically by using the -ScanOnly flag with the Submit command. When this option is used, the RC_UTILITIES_PARSING_STATUS table will contain information about each option and process statement used in the SUPERC program.

Table 32. Supported parameters in SUPERC

Parameter

Notes

LINECMP

May be an alias of LINE

DELTA

May be an alias of DELTAL

OVSUM

May be an alias of OVSUML

5.16. Query rewriting

DSNTIAUL, DSNUTILB, and DSNTEP2 can be extended with a plugin that rewrites the queries. For example, to rewrite Db2 queries to SQL Server queries.

A plugin that rewrites the queries (Db2 queries into SQL Server queries) is part of the distribution. This plugin uses cobrc for rewriting process and stores the results in a SQLite cache database.

To use this plugin, the utility must be called with two additional options -PluginPath=<QueryTranslation path> -Plugin=QueryTranslation

The plugin can be parametrized using different environment variables:

Table 33. Query rewriting plugin environment variables
Variable Default value Description

RC_SQL_REWRITE_CACHE_DIR

Temporary folder

The folder where the cache DB will be stored

RC_SQL_REWRITE_OPTION

:SQLRuntimeRewriting :MaxMem=2G :ScriptPaths="%RCDIR%/Scripts" :RewriteSQLProc=CastSubstrings.Rewrite :SQLSemanticRulesFile="%RCDIR%/sql/SQLSemanticRules.xml" :SQLRewritingRulesFile="%RCDIR%/sql/DB2ToSQLServerRewritingRules.xml" :SQLRewritingRulesFile="%RCDIR%/sql/DB2ToSQLServerRewritingRules_TimeConversion.xml" :SQLSupportSelectStar :SQL=sqlserver :SQLServerConnectionString = "connection string to the DB"

The options passed to cobrc

RC_SQL_REWRITE_OPTION_APPEND

The options that are appended to the default RC_SQL_REWRITE_OPTION

RC_SQL_REWRITE_DONT_USE_CACHE

FALSE

If set to TRUE, don’t use the cache DB to store the translated queries.

The SQLite cache database, named mssql-cache.sqlite, contains a single table cache with two columns: source and target. This database is in the directory %RC_SQL_REWRITE_CACHE_DIR%, if the database does not exist, the plugin creates it.

The %RC_SQL_REWRITE_CACHE_DIR% directory can also contain a second, optional, SQLite database named mapping-rewriting.sqlite. This database also contains a table named cache.

This can be useful if the translation process does not provide the expected result. For example, the target query needs to be optimized to achieve the expected performance.

The plugin searches for the query to be translated in the source column of mapping-rewriting.sqlite (if it exists). If the query is not found, it searches for it in mssql-cache.sqlite. If it is still not found, the plugin calls cobrc to translate the query and store the result into mssql-cache.sqlite.

If needed, a custom version of this plugin can be created. Its sources are available inside the samples directory of the installation: %RCDIR%\plugins\Batch\QueryTranslation.

5.17. IEBCOPY

The IEBCOPY JCL Utility allows for the copying and merging of Partitioned Datasets (PDS) and programs. This utility takes one or several datasets as input, and performs the action specified by the user, such as COPY or COPYGROUP (see the list of implemented options below). If no specific action is mentioned, and all the other prerequisites are met, a COPY action is performed by default.

Inputs and parameters

  • SYSUT1, if provided, this is the input dataset that will be copied or merged from.

  • SYSUT2, if provided, this is the output dataset, which serves as the destination of the operation.

  • Any additional named datasets may be used interchangeably as input or output, depending on the content of the PARM field or SYSIN.

  • Both PARM and SYSIN can contain control statements specifying the operation(s) IEBCOPY should perform, as well as the names of the input and output datasets to be used.

Example 1: Performing a simple COPY operation

//PSTEP00   EXEC PGM=IEBCOPY
//SYSUT1    DD  DSN=MY.PDS1,DISP=SHR
//SYSUT2    DD  DSN=MY.PDS2,DISP=SHR
//SYSIN DD *
            COPY OUTDD = SYSUT2, INDD = SYSUT1

In this example, the PDS pointed to by SYSUT1 will be copied into the PDS pointed at by SYSUT2. This is specified in SYSIN. The COPY command takes two parameters: OUTDD, the output dataset, which is the destination of the copy operation, and INDD, the dataset to be copied.

In a COPY operation, only one output dataset should be provided in OUTDD, but a list of input datasets can be provided in INDD.

Example 2: Performing a partial COPY operation

//PSTEP00   EXEC PGM=IEBCOPY
//SYSUT1    DD  DSN=MY.PDS1,DISP=SHR
//SYSUT2    DD  DSN=MY.PDS2,DISP=SHR
//SYSIN DD *
            COPY OUTDD = SYSUT2, INDD = SYSUT1
            SELECT MEMBER = (MEMBER1, MEMBER4)

In this example, MY.PDS1 contains three named members: MEMBER1, MEMBER2 and MEMBER4. MY.PDS2 contains three named members as well: MEMBER3, MEMBER5 and MEMBER6. In the SYSIN statement, the user specifies that a COPY operation should be performed, from SYSUT1 to SYSUT2, but that only MEMBER1 and MEMBER4 from SYSUT1 should be copied. This means that at the end of the operation, the output SYSUT2 will contain five members: MEMBER1, MEMBER3, MEMBER4, MEMBER5 and MEMBER6.

If a PDS member has the same name in the input and the output, the PDS member is not copied. In such a case, the user must explicitly specify that the output PDS member should be replaced. To do so, the SELECT statement should be rewritten as follows: SELECT MEMBER = ((MEMBER1,, R), MEMBER4), R standing for REPLACE.

Example 3: A compact COPY operation

//PSTEP00   EXEC PGM=IEBCOPY
//SYSPRINT  DD  DSN=IEBCOPY.DATA.DATALOG,DISP=SHR
//SYSUT1    DD  DSN=MY.PDS1,DISP=SHR
//SYSUT2    DD  DSN=MY.PDS2,DISP=SHR

In this example, SYSIN and PARM are empty. However, since SYSUT1 and SYSUT2 are provided, a COPY operation will be performed using SYSUT1 as input and SYSUT2 as output.

5.17.1. Implemented commands and options

Table 34. Supported commands and options in IEBCOPY

Command or option

Notes

COPY

Can be abbreviated to C. It takes two parameters, INDD (I) and OUTDD (O), respectively for inputs and output

SELECT MEMBER

Can be abbreviated to S M. Takes a list of PDS members as parameter, either in the form (MEM1, MEM2) (2 members to be copied), ((MEM1, NEWMEM1, R), MEM2) (2 members to be copied. If MEM1 exists in the output, it is overwritten by the MEM1 of the input, and is renamed NEWMEM1) or ((MEM1,, R), MEM2) (likewise, but MEM1 is not renamed in the output).

5.18. BPXCOPY

BPXCOPY is a JCL Utility that allows copying datasets, initially from a Mainframe-based system to a UNIX-based system. Unlike IEBCOPY, the user may manipulate the ownership of the copied dataset, for instance, the group owner and the owner of the copied dataset. This utility takes one sequential dataset or one member of a partitioned dataset (PDS) and a destination path for the copy as input.

Inputs and parameters

  • SYSUT1, is the input dataset that will be copied. This parameter is mandatory.

  • SYSUT2, is the destination path of the copied dataset. This parameter is mandatory.

  • SYSTSPRT, a dataset containing the program’s output, which is usually SYSOUT.

Unlike many other JCL Utilities, BPXCOPY exclusively relies on the PARM field for control options and statements. The options cannot be provided in SYSIN or in any additional dataset. The list of these options is available in the list of implemented options below.

Implemented options

Table 35. Supported parameters in BPXCOPY

Option

Notes

ELEMENT(element_name)

The only mandatory option. It accepts one parameter element_name, which is the name of the destination dataset.

GID(group)

It accepts one parameter, group, representing the group ID or group name of the copied dataset.

UID(owner)

It accepts one parameter, owner, representing the user ID or username of the owner of the copied dataset.

LINK(linkname1, linkname2)

Along with copying the dataset, several hard links to the copy may be created using this option.

SYMLINK(symlinkame1, symlinkame2)

Along with copying the dataset, several symbolic links to the copy may be created using this option. Requires SYMPATH to be applied.

SYMPATH(pathname1, pathname2)

It represents the path of the symbolic links pointing to the copied dataset. Requires SYMLINK to be applied.

According to the destination platform, several of these options may require elevated rights. The copy operation will fail if the user does not have the sufficient permissions to perform any of the operations requested by the program.
Both UNIX and Windows systems are supported, so files can also be copied to a Windows based system. The SYSUT2 PATH is initially provided as a UNIX path, which may be of restricted access on a Windows system. To avoid this potential issue, the default root of the path in the destination file system is set to the path of the default volume of the catalog manager. This value can be modified using the command-line argument -WindowsRootPath=.

Example 1: Performing a minimal COPY operation

//PSTEP00   EXEC PGM=BPXCOPY, PARM=ELEMENT(MYCOPY)
//SYSUT1    DD DSN=MY.DATASET,DISP=SHR
//SYSUT2    DD PATH='u/output_directory'
//SYSTSPRT  DD SYSOUT=*

In this example, the dataset pointed to by SYSUT1 will be copied to the destination path, which is the concatenation of the value of SYSUT2 and the parameter of ELEMENT. It means that MY.DATASET will be copied to the folder u/output_directory/, under the name MYCOPY.

Example 2: Performing a COPY operation and create a symbolic link

//PSTEP00   EXEC PGM=BPXCOPY, PARM='ELEMENT(ACOPY) SYMPATH(".\bpxcpylink") SYMLINK("cpylink")'
//SYSUT1    DD DSN=MY.DATASET,DISP=SHR
//SYSUT2    DD PATH='u/output_directory'
//SYSTSPRT  DD SYSOUT=*

In this example, the dataset pointed to by SYSUT1 will be copied to the destination path, which is the concatenation of the value of SYSUT2 and the parameter of ELEMENT. It means that MY.DATASET will be copied to the folder u/output_directory/, under the name ACOPY. In addition, a symbolic link to this copy is created in the destination file system; its path is u/output_directory/bpxcpylink/cpylink. It means that the symbolic link called cpylink is pointing to the copied dataset located in u/output_directory/ACOPY. Creating a hard link also follows the same logic.

Example 3: Performing a COPY operation to a Windows destination system

//PSTEP00   EXEC PGM=BPXCOPY, PARM=ELEMENT(MYCOPY)
//SYSUT1    DD DSN=MY.DATASET,DISP=SHR
//SYSUT2    DD PATH='u/output_directory'
//SYSTSPRT  DD SYSOUT=*

As in the other examples, the destination path is u/output_directory. If the destination system is Windows-based, it is possible to call this program using the -WindowsRootPath= flag to set the root folder. For instance, using the following command %RCBIN%/Submit.exe -File=BPXCOPYCOPERATION.jcl -WindowsRootPath="C:\myfolder" will copy MY.DATASET to C:\myfolder\u\output_directory.

5.19. FILEBKUP

The FILEBKUP utility provides dataset backup and restore capabilities using ZIP archives. It works like mainframe JCL, making it easy to use in batch jobs.

5.19.1. Execution Modes

  • Backup Mode (default): Creates a ZIP archive of selected datasets.

  • Restore Mode: Restores datasets from a backup archive. Activated by passing the -RESTORE flag, or calling PGM=FILERSTR.

Restore works directly from the contents of the backup archive: each dataset is matched and recreated from the metadata stored in the ZIP file. Because of this, the dataset (or its catalog entry) does not need to still exist for it to be restored — a dataset that was deleted, or an entire catalog that was lost, can be restored as long as a matching backup archive is available.

5.19.2. JCL Interface

FILEBKUP can be paramterized using 3 datasets as you can see in the following examples.

Briefly: * SYSIN contains the list of datasets to include/exclude/rename * BKUPDIR defines the backup directory (can also be set via environment variable) * ARCHIVE defines the logical name of the backup (used as prefix for backup files and to locate archives during restore)

5.19.3. SYSIN Parameters

  • INCDSN(DSN pattern) or INCLUDE(DSN pattern): Includes datasets matching the specified pattern.

    • Supports wildcards: (single qualifier) and * (multiple qualifiers).

    • Pattern format is similar to IDCAMS LISTCAT.

  • EXCDSN(DSN pattern) or EXCLUDE(DSN pattern): Excludes datasets from the included list.

    • Supports wildcards: and *.

  • RENAME(from pattern,to pattern): Restore mode only. Renames a matched dataset while it is being restored.

    • Both the source and target pattern must end with a wildcard: (captures exactly one qualifier) or * (captures the remaining zero or more qualifiers).

    • Example: RENAME(AC1.*,AC1.RST.) restores AC1.DATA.MASTER as AC1.RST.DATA.MASTER.

    • Example: RENAME(AC2.DATA.,AC2.RST.) restores AC2.DATA.PARAM as AC2.RST.PARAM.

    • Several RENAME entries can be provided; the first pattern that matches a given dataset is applied.

    • A dataset matched by INCLUDE/EXCLUDE that has no matching RENAME pattern is restored under its original name.

  • RETPD=n: Number of days to retain backup copies. Backups older than n days are automatically deleted when a new backup is created. Applies to backup mode only.

RETPD is ignored during restore.
INCLUDE/EXCLUDE wildcards are supported for both backup and restore.

5.19.4. ARCHIVE DD Statement

The ARCHIVE DD statement defines the logical name used for the backup file.

//ARCHIVE DD *
MY_BACKUP
/*
  • During Backup: the name is used as a prefix for the generated ZIP file: <BACKUP_FOLDER>/MY_BACKUP_<timestamp>.zip

  • During Restore: the name is used to find the most recent matching archive: <BACKUP_FOLDER>/MY_BACKUP*.zip
    To target a specific file, provide the full filename with the .zip extension.

5.19.5. Backup Directory

A backup directory must be specified using either:

  • The BACKUP_DIR environment variable, or

  • The BKUPDIR DD statement (takes precedence over the environment variable).

Examples:

  • Windows: C:\mybackup\

  • Linux: /mnt/backup/raincode

5.19.6. JCL Examples

Backup
//BACKUP JOB
//*
//STEP1 EXEC PGM=FILEBKUP
//SYSIN DD *
 INCLUDE(MY.**) -
 EXCLUDE(MY.TEST.DATASET) -
 RETPD=2
/*
//BKUPDIR DD *
d:/tmp/rcbackup
/*
//ARCHIVE DD *
MY.BACKUP
/*
Restore

The following restores datasets by matching them against the contents of the most recent archive matching MY.BACKUP*.zip in d:/tmp/rcbackup. MY.** matches every dataset whose name starts with MY., except MY.TEST.DATASET, which is excluded. Each restored dataset is renamed under the MY.RESTORED. prefix, so MY.DATA is restored as MY.RESTORED.DATA.

//RESTORE JOB
//*
//STEP1 EXEC PGM=FILERSTR
//SYSIN DD *
 INCLUDE(MY.**) -
 EXCLUDE(MY.TEST.DATASET) -
 RENAME(MY.**,MY.RESTORED.*)
/*
//BKUPDIR DD *
d:/tmp/rcbackup
/*
//ARCHIVE DD *
MY.BACKUP
/*

The RENAME clause is optional; a restore invocation with only INCLUDE/EXCLUDE clauses restores matched datasets under their original names, for example:

//RESTORE JOB
//*
//STEP1 EXEC PGM=FILERSTR
//SYSIN DD *
 INCLUDE(MY.**) -
 EXCLUDE(MY.TEST.DATASET)
/*
//BKUPDIR DD *
d:/tmp/rcbackup
/*
//ARCHIVE DD *
MY.BACKUP
/*

5.19.7. Dataset Handling

Standard Datasets

Sequential, PDS, and GDG datasets are archived and restored directly, without conversion.

VSAM (KSDS) Datasets

VSAM datasets cannot be archived directly. Before adding one to the archive, the utility converts its data to a sequential format using REPRO, staging it in a temporary dataset in the current job step’s output area. This staging dataset is not cataloged and does not need to be cleaned up manually. On restore, the sequential data is extracted to a similar temporary staging dataset and loaded back into the VSAM dataset using REPRO.

This applies regardless of whether the catalog is stored on disk or in a database.

GDG Handling
  • Backup: GDG generations are resolved and each physical generation is included in the archive.

  • Restore: All generations present in the archive are restored.

5.19.8. Retention Management

When RETPD=n is specified, old backups sharing the same name prefix are automatically deleted at the start of each new backup run. A backup is deleted if it is the N + 1 older copy.

5.19.9. Error Handling

The utility aborts with a user error (condition code 4095) if any of the following are missing or invalid:

  • No SYSIN input provided (neither via SYSIN DD nor -INPUT= argument).

  • No backup name provided (neither via ARCHIVE DD nor as a positional argument).

  • No backup directory defined (BACKUP_DIR environment variable or BKUPDIR DD).

  • The specified backup archive is not found during restore.

  • A dataset listed in SYSIN is not found in the catalog (backup mode).

5.20. ZIP390

The ZIP390 utility aims to handle and exchange datasets. Specifically, the Raincode implementation enables dataset compression and supports sending emails with or without attachments.

ZIP390 takes its arguments from SYSIN. The user must first specify which ACTION they want to perform (either ZIP for archiving a dataset, or EMAIL to send an email that may contain an attachment). Then, depending on the intended action, several other fields may be required. For instance, if the user wants to send an email, the fields HOST, FROM, and TO are required.

The four examples below illustrate the different use cases currently implemented in Raincode ZIP390

Example 1: Sending a simple email with one or several recipients

//STEP020  EXEC PGM=ZIP390
//SYSIN    DD   *
ACTION=EMAIL
HOST=EMAIL/localmail.example.com/25
FROM=from@example.com
TO=to1@example.com
TO=to2@example.com
TO=to3@example.com
SUBJECT=Test message - job ZIP390_email_only
BODY:
Hello,

This is an example of a simple email with no attachment.

Regards,
END:
/*

In this example, the user wants to send an email with no attachment. The fields HOST, FROM, and TO are required. If SUBJECT is omitted, the email is sent with an empty subject. The body of the email is enclosed between BODY: and END:. However, the body of the email may be omitted as well.

Each additional recipient requires an additional TO= field.

Example 2: Sending an email with one simple attachment

//STEP020  EXEC PGM=ZIP390
//COVERDD  DD   *
Please find attached the invoice for this billing period.
/*
//SYSIN    DD   *
ACTION=EMAIL
HOST=EMAIL/localmail.example.com/25
ATTACH=SEQ/COVERDD;COVER.TXT
FROM=from@example.com
TO=to@example.com
SUBJECT=Invoice 2026-0617-001
BODY:
Dear customer,

Please find attached your invoice.

Regards,
Billing department
END:
/*

To add an attachment to an email, add the ATTACH field. It should contain the name of the dataset to be attached. The dataset name is prefixed by the type of the dataset. For now, Raincode supports SEQ (sequential dataset) and DSN (dataset).

It is possible to customize the name of the attached dataset. For instance, if the original dataset is named FOO.seq, the user can provide an alternate name for the attachment by suffixing it to the ATTACH field after a semi-colon. For instance ATTACH=SEQ/FOO.seq;FOOBAR.seq, where FOOBAR.seq will be the name of the attachment.
It is possible to attach datasets present in the catalog, as well as inline datasets like in the JCL excerpt above.

Example 3: Zipping a dataset

//STEP020  EXEC PGM=ZIP390
//LOGDD    DD   *
2026-06-17 01:00:00 INFO  Batch run started
2026-06-17 01:00:05 INFO  Batch run finished, rc=0
/*
//SYSIN    DD   *
ACTION=ZIP
IFILE=SEQ/LOGDD;RUNLOG.TXT
IFILE=DSN/ZIP390.TEST2.SUMMARY;SUMMARY.TXT
ARCHIVE=DSN/WEEKLY.ZIP

To compress a dataset, use the ACTION ZIP instead of EMAIL. The dataset name to be archived should be provided in the IFILE field. Similar to Example 2, the dataset should be prefixed by its type (DSN or SEQ), and can be suffixed by an alternate name after a semi-colon. The name of the archive is provided in the ARCHIVE field.

Example 4: Sending an email with mixed attachments

//STEP030  EXEC PGM=ZIP390
//SEQDD1   DD   *
Inline SEQ content #1, included in the zip as SEQDD1.
/*
//SEQDD2   DD   *
Inline SEQ content #2, attached unzipped as plain text.
/*
//SYSIN    DD   *
ACTION=ZIP
IFILE=SEQ/SEQDD1
IFILE=DSN/ZIP390.TEST5.DATA1;DATA1.TXT
ARCHIVE=EMAIL/localmail.example.com/25/FULL.ZIP
ATTACH=SEQ/SEQDD2;EXTRA1.TXT
ATTACH=DSN/ZIP390.TEST5.DATA2;EXTRA2.TXT
FROM=from@example.com
TO=to1@example.com
TO=to2@example.com
SUBJECT=ZIP390 full scenario test
BODY:
Hello,

This message exercises every ZIP390 clause: IFILE (zipped),
ARCHIVE=EMAIL, ATTACH (unzipped) and multiple TO recipients.

Regards,
Batch platform
END:
/*

This use case covers a more complex scenario in which an email contains multiple attachments. Some of the attachments are archived, while others are left unchanged. This use case requires the ZIP ACTION keyword, even though an email is being sent.

In a first step, the datasets to be attached are processed: SEQDD1 and ZIP390.TEST5.DATA1 are zipped together in an archive named FULL.ZIP. Then, two other datasets are attached to the email: SEQDD2 and ZIP390.TEST5.DATA2. This means the email will contain three attachments: the ZIP archive and the last two datasets.

In this case, it is not necessary to explicitly provide the HOST field. It can be inlined in the ARCHIVE field, for example ARCHIVE=EMAIL/localmail.example.com/25/FULL.ZIP.

6. Catalog Explorer

The Catalog Explorer is a graphical user interface for accessing Raincode JCL catalog. The Catalog Explorer helps manage datasets of type File, PDS, and GDG.

This tool makes it easy to differentiate different datasets and see the metadata about the datasets without having to parse the XMLs manually.

For more details, refer to the Catalog Explorer Manual.

7. JCL Character Encoding

Character encoding (and decoding) refers to the process of transforming a set of characters to and from a sequence of bytes. The mainframe uses EBCDIC encoding, while most open systems, such as Windows or Linux, work using ASCII encoding. As a result, migrating from a mainframe requires addressing how character encoding will be handled.

For more information on character encoding and codepages in .Net, refer to the Microsoft documentation on the API for System.Text.Encoding.

In the remainder of this section, the following two codepages will be used as examples: number 500 is IBM EBCDIC (International), an EBCDIC code page with full Latin-1-charset support used in IBM mainframes, and number 1252 is the well-known Western European (Windows) codepage. Note that the former is not natively supported in .Net

7.1. Configuration settings and autodetection

There are two configuration settings in the Raincode Catalog that determine how character encoding is treated: defaultCodePage and codePages. The latter also determines autodetection of codepage behaviour, so it is covered here as well.

7.1.1. defaultCodePage attribute

The defaultCodePage attribute is mandatory; it defines the code page used by the system to store data files and source files.

  • Instream data found in JCLs are stored on disk using the encoding specified in the defaultCodePage

  • Unless overridden by a codePages element configuration, JCLs are read using the defaultCodePage

  • Submit assumes the encoding specified in defaultCodePage is used by the stack runtime

  • All newly created datasets [DISP=NEW] will use the defaultCodePage

  • The RC_CODEPAGE environment variable is set to this value before calling step programs. The effect of this is to enforce defaultCodePage as the default code page for any Raincode utility.

  • The output files produced by utilities like DSNTIAUL/DSNUTILB will use defaultCodePage to encode data.

7.1.2. codePages element

The codePages element in the catalog configuration file contains two attributes, jclAlternate and jclRewrite, as described in the table next.

Table 36. codePages element attributes
Attribute Type Format

jclAlternate

String

<Codepage identifier>

jclRewrite

String

`"Alternate"' or `"Default"'

jclRewrite is the codepage used to write JCL and PROCLIB on disk in the SYSOUT folder. If this is set to "Alternate" , the codepage specified in jclAlternate will be used. Otherwise, i.e. if undefined or "Default", the defaultCodePage will be used.

For example, if defaultCodePage="500", the value jclAlternate="1252" means the user expects JCL and PROCLIB to be written as ASCII on the disk when Submit reads the file.

jclAlternate is also the auto-encoding detection alternative codepage when reading a JCL or a PROCLIB, as discussed next.

7.1.3. Autodetection

In some situations, a user may need as many JCLs as possible to be in the ASCII encoding, yet some remain in EBCDIC for a specific reason (automatic conversion of the catalog, part of PROCLIB written by an application program, …). To allow this, Raincode provides Autodetection of Encoding of JCL and PROCLIB between the default encoding and the alternate encoding, both as specified above.

With jclAlternate set, when reading a JCL or a PROCLIB, SUBMIT will test for the “//” pattern as the beginning of the first line of the JCL. It will read the first two bytes of the file and use both encodings to determine which one translates those bytes to “//”. This encoding is then used to read the entire JCL.

7.2. JCL Character Encoding Strategies

There are three main strategies on how to treat character encoding:

7.2.1. Pure ASCII Encoding

When using purely ASCII, the JCL, PROCLIB and data files are encoded in an ASCII codepage. To do this, programs are compiled with StringRuntimeEncoding set to ASCII and the defaultCodePage in the Raincode catalog is ASCII , e.g. 1252.

The ASCII code page is the default for Raincode tools as it is the native encoding to Windows and Linux servers.

Advantages:

  • All third-party tools use the same ASCII encoding; it is more natural for an open system.

Disadvantages:

  • Files must be converted when transferred (from and to the Mainframe).

  • The collating sequence is different to EBCDIC, and so the result of the sort may be different.

  • When validating the migration, comparing the result file is more complicated due to the difference in encoding and collating sequence.

7.2.2. Pure EBCDIC Encoding

When using purely EBCDIC, i.e. the native encoding of the mainframe, the JCL, PROCLIB and data files remain encoded in an EBCDIC codepage. Programs are compiled with StringRuntimeEncoding set to EBCDIC, and the defaultCodePage in the Raincode Catalog is EBCDIC , e.g. 500.

Advantages:

  • Files do not need to be converted.

  • The collating sequence is identical as on the mainframe.

  • Validation of the migration by comparing the result file is more effortless.

Disadvantages:

  • Third-party tools need to be able to use EBCDIC, which complicates data manipulation.

  • Source editing requires a text editor that supports the EBCDIC codepage.

7.2.3. Mixed Encoding

In a mixed encoding, data files are stored in EBCDIC and JCL and PROCLIB files are stored in ASCII or EBCDIC.

Programs are compiled with StringRuntimeEncoding set to EBCDIC, and the defaultCodePage in the Raincode Catalog is EBCDIC , e.g. 500. In addition, the codePages jclAlternate needs to be set to ASCII, e.g. jclAlternate="1252" (see the section on Autodetection for more information on the effect of jclAlternate).

This setting fundamentally allows data to be processed and stored in EBCDIC while sources are stored and edited in ASCII for convenience. In addition, the autodetection process allows JCL and PROCLIB files to be also stored in EBCDIC, permitting JCL and PROGLIB files to be generated by a program (which produces its data in EBCDIC format).

The stack compiler has options (for more details, refer to Encoding) to define the Encoding of runtime and sources.

Advantages:

  • Data files do not need to be converted.

  • The collating sequence is identical as on the mainframe.

  • Validation of the migration by comparing the result file is more effortless.

  • Editing of JCL may be done with standard third-party tools.

Disadvantages:

  • Third-party tools need to be able to use EBCDIC, which complicates data manipulation.

  • To be editable in standard third-party tools, JCL files need to be converted to ASCII.

7.3. DD CARD Codepage Enforcing

For some operations, you may need to be able to enforce the encoding format, overriding the default format. This as some third-party utilities may require JCL instream data to be encoded in a specific codepage, or the encoding of the output file of the DSNTIAUL and DSNUTILB utilities may need to in a specific codepage.

Raincode JCL provides two extensions to the JCL DD statement: CODEPAGE=<integer value> and AUTOENCODE=<YES/NO>. The CODEPAGE setting overrides the default codepage that is specified in the catalog configuration file. AUTOENCODE=YES will allow the runtime to transparently convert the content of the file to the actual encoding that is being used by the runtime, if needed.

For example, in the JCL below the CODEPAGE=1252 is used to enforce the encoding of the instream commands on disk to be 1252. This allows third-party tools to easily work with the files. If the runtime uses EBCDIC (e.g. when using Pure EBCDIC Encoding or Mixed Encoding) then AUTOENCODE=YES ensures that it will transform the contents of the file to EBCDIC encoding before passing it to the program MYPROG.

//STEPXXX EXEC PRG=MYPROG
//INFILE DD CODEPAGE=1252,AUTOENCODE=YES,*
 Instream command 1
 Instream command 2
 ...
/*

Similarly, the CODEPAGE argument in the DD statement of the output file for the programs DSNUTILB and DSNTIAUL will modify the encoding of the output file to the specified codepage.

Auto encoding supposes that the file is a pure text file and will blindly transform its contents. Consequently, if the file contains binary data, then this data will also be remapped, which will corrupt the file.

8. VSAMSql

8.1. Introduction

The idea behind VSAMSql is to store the dataset data and meta information (i.e. the properties of a dataset, see also Mainframe file system emulation) in a database instead of on a file system.

vsamsql
Figure 33. VSAMSql is a file driver

All the Raincode tools and compiled programs use the file driver to access the files (i.e. datasets). To store the data in a database instead of on disk, the VSAMSql file driver is provided that redirects input-output instructions to the database. Consequently, all the programs that use the file driver interface can store data in the database seamlessly, as illustrated in the figure above.

The VSAMSql driver is designed such that one table can contain the data of multiple files, as long as each of them has the same properties, i.e. record length, key position, record type and record structure.

8.2. Catalog configuration

The Raincode catalog is configured to use VSAMSql for specific datasets through the datasetSqlMapping element of the catalog configuration file. For more details, refer to the Catalog configuration section.

The datasetSqlMapping element holds datasetTemplate child elements that map the files to the corresponding table in which the data must be stored, as described in Dataset mapping with tables. For each table, a datasetTemplate element declares the name of the table and the plan to use to connect to the database. One or more pattern elements use regular expressions to identify the files (Unit and DSN) mapped to the table. The parameters element describes the record: its length and keys.

Additionally, the catalog configuration file contains information about where the catalog should be stored (on the file system or in a database) and whether the file should be stored in the database or the file system. The attribute catalogFormat describes the location of the catalog: disk – the catalog is stored on the file system; db – the catalog is stored in the database; if the catalogFormat is db, catalogDbConnection is the plan/connection string. For more details, refer to map plan name to actual connection string to connect to the database. If the catalog is stored in the database, two tables are used to store the catalog information: CATALOG_META and CATALOG_LOCK.

8.3. Database model

8.3.1. Tables

The table VSAM_META contains meta-information about the files stored in the database:

  • ID: an SQL Server identity column

  • FILE_NAME: the name of the file

  • TABLE_NAME: the name of the table in which the data of this file are stored

  • PARTITION: the partition number (see Partitions)

A table can store data from multiple files, provided that all the files have the same structure, including the same record length, keys, and record structure. Each data table contains the following columns:

  • RID: an SQL Server identity column

  • FILE: the foreign key to the VSAM_META.ID column

  • PARTITION: the partition number (see Partitions)

  • Data: the actual data as a binary array (VARBINARY)

  • KEY: this column is only present for the VSAM file. It contains the key of the record. It is a computed-persistent column that is a substring of the Data column.

  • KEY_[1…​n]: there is one column for each alternate key of the VSAM file. It is a computed-persistent column that is a substring of the Data column.

If the catalog is stored in the database, two additional tables are created: CATALOG_META and CATALOG_LOCK.

CATALOG_META contains information about the catalog. There is one line representing each file.

CATALOG_LOCK is used to manage the locking of the files.

8.3.2. Partitions

When a file needs to be deleted, all its records must be deleted from the table. Deleting many rows (records) from a table with a DELETE statement is inefficient because lines are deleted individually. If the table contains only one file, the statement TRUNCATE can be used more efficiently.

If the table is partitioned, TRUNCATE can be used to delete all the data of one partition. So, if a table contains more than one file, one partition can be used for each file. Similarly, when a file needs to be deleted, TRUNCATE can be used to delete all the data of the corresponding partition.

During the generation of the creation script, the partitions element of the catalog configuration is used to know which partition need to be created. If a file isn’t associated with a partition, its data will be stored in the default partition (partition 0).

8.3.3. Stored procedures

One stored procedure is associated with each data table: DELETE_<table name>. This stored procedure is used to delete all the data of a file. It decides if DELETE or TRUNCATE should be used, depending on how many files are stored in the partition.

Some stored procedures are used to manage the catalog: WRITE_CATALOG, KEEPLOCK_CATALOG, LOCK_CATALOG, UNLOCK_CATALOG.

8.3.4. Database creation

The creation script of the database is generated by VsamSql.DbGenerator. This program reads the catalog configuration file, whose path is given as an argument, and generates a SQL file that contains the tables creation SQL script. This SQL script then needs to be executed on the database server.

VsamSql.DbGenerator can take a connection string to the database as an argument (-SqlDatabase), then it generates only the missing tables and updates the partition function.

An example table script generation is as follows:

VsamSql.DbGenerator.exe -CatalogConfiguration="C:\ProgramData\Raincode\Batch\Raincode.Catalog.xml" -OutputFile="output.sql"

For more details on VsamSql.DbGenerator arguments refer to command line options.

8.4. View creation

The Data column is binary data: the array of bytes corresponding to the COBOL or PL/I program record. In those programming languages the records are read as one array of bytes and are transparently mapped to a variable. This variable is usually defined in a copybook or include, and is composed by a hierarchy of sub-variables meaningful to the application. The application then accesses the sub-variables directly instead of working with the array of bytes that is the record.

To aid in developing programs that use VSAMSql that aren’t written in COBOL or PL/I, VSAMSql allows for the definition of views. The idea here is that these views decompose the Data column based on the variables defined in a COBOL or PL/I program, as shown in the following figure.

viewcreation
Figure 34. View creation

Triggers are associated with the view, enabling them to be used to both query and update the data.

The view can be created as below:

  1. Use the COBOL or PL/I compiler to extract variable declarations from the program source code into an xml file:

    cobrc.exe :DeclDescriptors= "output_xml_file.xml" :MaxMem=1G "cobol_program_or_copybook" :SQL=SqlServer
  2. Use CopybookViewGenerator to generate the view and trigger the creation script from this xml file:

    CopybookViewGenerator.exe -xml="output_xml_file.xml" -struct=NAME_OF_COBOL_VAR -table=TABLE_NAME -output="OUTPUT_FILE.sql" -conn="connection string to the DB"
  3. Before executing the SQL script created from the above step, ensure the following SQL scripts are executed: EbcdicFuncs.sql and Functions.sql (these are part of the compiler installation and can be found in "%RCDIR%\sql\CopybookViewGenerator").

8.5. Granting Permissions to Database Users

Specific access permission must be granted to allow a database user to interact with tables, stored procedures and functions within the VSAMSql environment.

  • Reader Access allows a database user to retrieve and view data from tables within the specified VSAMSql environment.

  • Writer Access allows a database user to insert, update or delete data from tables within the specified VSAMSql environment.

  • Execute Access grants a database user the right to execute the stored procedures and functions within the specified VSAMSql environment.

For more details on the generated stored procedures and functions, refer to the following files:

  • output.sql: created during database creation.

  • OUTPUT_FILE.sql: created during view creation using CopybookViewGenerator.

  • Ebcdic.sql and Functions.sql: included in the compiler installation and located in "%RCBIN%\sql". They provide additional stored procedures and functions to support VSAMSql environment.

8.6. Load data

Data must be loaded into the tables while creating the catalog and database objects (such as tables, indexes, and views).

There are two ways to load data:

  • Using JCL: Copy the data from a disk file into VSAMSql.

  • Using the SQL Server bcp utility:bcp requires a more complex setup and is more efficient for handling large volumes of data.

8.6.1. Loading data using a JCL

Loading data using a JCL is the same as migrating a dataset, as described in Dataset Migration, because JCL sees the VSAMSql file as a dataset.

8.6.2. Loading data using bcp

The VsamSql.load utility does not directly load the data. Instead, it prepares the data to be loaded by the high-performance SQL Server bcp utility, specially designed for bulk data insertion into the SQL Server. This process involves transforming the input file into a format compatible with bcp. It generates a format file (.fmt) that specifies the format argument used by the bcp to import the data.

Once the data has been processed and all the output files are created, they must be loaded into the target SQL Server database using bcp.

For the demonstration on how to load the data using VsamSql.load and bcp refer to an example script, VsamSql.LoadData.ps1 located at "%RCDIR%\scripts\VsamSql".

You can also refer to the VsamSql.Load Command Line Options for details on how to use this tool.

8.7. Caches for read, write and update

In VSAMSql, multiple caches are implemented, each targeting a different kind of file use:

  • A prefetch or read-ahead cache for sequential read file access. It is fully flushed when a START, READ KEY, (re)write, delete, or a change in the read direction occurs.

  • An update cache for read and update operations in random file access, if the file is indexed by one unique key. It is partially flushed when it is full, and more space is needed, and fully flushed when the maximum number of writes or updates per commit is reached.

  • A write cache for inserting new records, either in sequential or random file access. It is fully flushed when it becomes full, when the maximum number of writes or updates per commit is reached, or when a READ or START is performed.

It goes without saying that all caches are flushed (in their respective ways) when closing the file. The size of caches, as well as the number of writes for automatic commit, can be defined per file or per job, as described below. A cache size of 0 effectively disables that cache.

The caches require that in the VSAMSql connection string, the setting MultipleActiveResultSets=True is set.

8.7.1. Prefetch and Write cache considerations

The prefetch or read-ahead cache for sequential file read access enhances performance by retrieving records in advance and in bulk. The cache size is dynamic: at the first read, it is filled by fetching 10 records from the database. If a cache miss occurs, i.e., all 10 have been read, the cache is cleared, the size is multiplied by 10 and it is filled again by querying the database (for 100 records). Each such cache miss causes the cache size to be multiplied by 10, up to the prefetch limit defined in the cache configuration. A START, READ KEY, (re)write, delete, or a change in the read direction clears the cache and sets its size to 10 records. Also, a START does not fill the prefetch cache, only 1 record is read.

The write cache is typically useful when a significant amount of records are added to a sequential file. The write cache will store records into the cache and send writes to the database in a bulk write operation. To use this cache, all keys should be unique.

Use the write cache only when you are certain that all keys are unique. Primary key uniqueness is validated only during the bulk write operation, not at the time the record is written by the program. Consequently, any program logic for handling duplicate keys will be ineffective, and the program will fail at cache flush time rather than at record write time.

8.7.2. In detail: the workings of the update cache

The update cache stores both read and update operations, though it does not cache the insertions of new records.

The cache works as follows:

  • A read of a record causes it to be cached, and subsequent reads or writes of that record occur on the cache until that record is evicted, i.e. written to the database (if updated) and removed from the cache.

  • When a commit occurs, either due to the commitRate being reached or the file being closed, all updates are evicted before the commit.

  • Alternatively, when the cache is full, some of the oldest updated records will be evicted to make space for new reads (but no commit occurs unless commitRate is reached).

  • The cache is conservative: any operation that cannot be performed safely when operated on the cache will cause a complete cache eviction, followed by the operation performed directly on the database. For instance, a record update that changes the value of a unique key cannot be performed on the cache, but on an up-to-date version of the database, which must then be able to reject the update if it violates a unique key constraint. This rejection must happen immediately, and cannot be deferred to a future eviction of the cache.

  • The cache is also transparent: it does not require any changes to the application program that can thus read and write records without caring which of these operations will be optimized by the cache. Strict functional equivalence is guaranteed in all cases.

VSAMSql performance for reads and updates is then improved by a combination of two factors:

  • Re-reading a cached record replaces a costly database operation with an efficient in-memory counterpart.

  • When the records in the caches are evicted to the database, the updates are performed in bulk, instead of one by one if there were no cache.

8.7.3. Configuring the caches: lookup order

The size of caches, as well as the number of writes required for automatic commit, can be defined in many different ways. The driver takes the following steps to determine which values to use for cache sizes:

  1. If there is a SUBSYS=(VSQL, …​) statement in the DD statement of the JCL (see Configuration in the JCL), that value is used.

  2. If there are cache values declared in the .meta of the file, these are used. These are placed there at file creation time when there are entitites in a DriverParameter element of the dataset template that is not specific to a job, step or program. This is described in Unrestricted parameters.

  3. If the dataset template for the file contains job- or step- specific DriverParameter entities that apply, any entities giving cache values are used, as described in Job, Step or Program Specific parameters.

  4. If no values have been encountered, the default values for the driver, as described in Defaults are used.

8.7.4. Configuration in the Driver Settings

The size of caches can also be configured without editing JCLs. To achieve this, there are multiple ways in which changes can be made to the dataset template for the file, in the <datasetTemplate> XML element of the file.

The most straightforward way to do this, is to add attributes to the XML element, and the available attributes are as follows:

  • prefetch: Specifies the maximum size of the prefetch cache, in records, for sequential reads from VSAM. Prefetching enhances performance by retrieving records in advance and in bulk, thereby reducing the number of SQL queries and minimising network latency.

  • updateCache: Specifies the size of the update cache, in records. It stores read records as well as record updates. Re-reading cached records avoids database accesses. Updated records (rewrites) are stored in this cache and then sent to the database as a bulk operation. This reduces the network latency by minimizing the number of database update calls.

  • writeCache: Specifies the size of the write cache, in records, for insert operations. This is typically useful when a significant amount of records are added to a sequential file. The write cache will store records into the cache and send writes to the database in a bulk write operation.

  • commitRate: Specifies the number of write/update operations that cause an automatic COMMIT to the database. Set to -1 to disable intermediate commits and commit only at the end of the program.

As mentioned previously, a cache size of 0 effectively disables that cache.

8.7.5. Job, Step or Program Specific parameters

As detailed earlier, in how to enable VSAMSql, in the <driverParameter> tag, attributes can be added that make these parameters be specific to a job, a step or a program. This effectively allows for cache values to be set for specific scenarios, without needing to edit JCLs.

If the job, step or program creates a VSAM file, the cache parameters are added to the .meta of that file. Alternatively, if the job, step or program reads or writes a VSAM file, the cache parameters are used for these accesses.

Inside the <driverParameter> entity, entities can be added that specify the values for the different caches (see above for a fuller description):

  • <prefetch>: Specifies the maximum size of the read ahead cache.

  • <updateCacheSize>: Specifies the size of the update cache.

  • <writeCache>: Specifies the size of the write cache.

  • <commitRate>: Specifies the number of write/update operations that cause an automatic COMMIT to happen.

8.7.6. Unrestricted parameters

If the <driverParameter> tag has none of the attributes that restrict to job, step or program, these configuration parameters take effect at file creation time (since they are placed in the .meta file).

If these values are changed in the catalog after a file has been created, these changes will not take effect on that file.

For example, suppose we have the following cache configuration, for the VsamLite driver (with nonsensical values):

<datasetSqlMapping>
    <datasetTemplate driver="VsamLite">
        <pattern>
        [...]
        </pattern>
        <driverParameter>
          <prefetch>www</prefetch>
          <updateCacheSize>xxx</updateCacheSize>
          <writeCache>yyy</writeCache>
          <commitRate>zzz</commitRate>
        </driverParameter>
    </datasetTemplate>
</datasetSqlMapping>

Whenever a file gets created, the cache settings are placed in the <FileConfig> element in the .meta as follows:

<FileConfig>
    <DriverAssembly>VsamLite</DriverAssembly>
    <DriverParameters>
      <prefetch>www</prefetch>
      <updateCacheSize>xxx</updateCacheSize>
      <writeCache>yyy</writeCache>
      <commitRate>zzz</commitRate>
    </DriverParameters>
</FileConfig>

Do note the difference in the <DriverParameters> tag: plural versus singular.

While it is possible to manually edit these values in the .meta of a file, we urge caution. There is no error-checking on these values when the .meta file is read, and incorrect tags or values will lead to unexpected behavior.

8.7.7. Configuration in the JCL

In some cases, caching needs to be fine-tuned for a specific job step, and this can be done in the JCL itself. This configuration overrides all other configurations, allowing for fine-grained tuning.

For each DD statement that references a VSAMSql dataset, you can define caching parameters that apply only to that step by using:

SUBSYS=(VSQL,...)

The keywords for the different values are as follows (see above for their meaning):

  • READ or PREFETCH: The maximum size of the prefetch cache, in records.

  • WRITE or WRITECACHE: The size of the write cache, in records.

  • UPDATE or UPDATECACHE: The size of the update cache, in records.

  • COMMIT or COMMITRATE: The commit rate.

For example, when unloading a VSAM to a flat file, a large PREFETCH cache is useful.

//STEPULD     EXEC=IDCAMS
//FILEIN      DD  DSN=...,
//            SUBSYS=(VSQL,’PREFETCH=5000’)
//FILEOUT     DD DSN=...
//SYSIN       *
REPRO FILEIN(FILEIN) TO FILEOUT(FILEOUT)
/*
VSAMLite Driver Options

The following settings apply specifically to the VSAMLite driver (VSAMSql using SQLite as the backend).

Exclusive Mode
SUBSYS=(VSQL,'EXCLUSIVE')

This option opens the file in exclusive mode, restricting access to a single process.

Benefits:

  • Ensures exclusive access to the file

  • Prevents concurrent reads or writes by other processes

  • Significantly improves performance.

Limitations:

  • The file cannot be accessed by any other process while in use.

No Journal Mode
SUBSYS=(VSQL,'NOJOURNAL')

This option disables the SQLite’s journaling mechanism.

Benefits:

  • Reduces I/O overhead

  • Improves overall performance

  • Can be combined with EXCLUSIVE mode.

Limitations:

  • If the process is interrupted without a clean file closure, the file may be left in an inconsistent or unstable state.

  • This option must be used only for temporary data or files that can be fully rebuilt or reloaded without impact.

8.7.8. Defaults

If no values for cache sizes have been set, defaults are used. The different caches have the following default values:

Parameters Default Value

READ

100

UPDATE

100

WRITE

0

COMMIT

-1

You can customize these default values in the Raincode Catalog file by adding a datasetSqlMappingDefault entity inside catalogConfiguration that specifies default values in the following form:

<datasetSqlMappingDefault>
    <vsamUpdateCache>www</vsamUpdateCache>
    <vsamWriteCache>xxx</vsamWriteCache>
    <vsamPrefetch>yyy</vsamPrefetch>
    <vsamCommitRate>zzz</vsamCommitRate>
 </datasetSqlMappingDefault>

8.8. VSAMSql Local Copy Mechanism

8.8.1. Scope

In certain batch jobs, VSAMSql access time remains too high despite standard optimizations such as query tuning and caching. This usually happens in steps that perform a very large number of VSAMSql accesses, where the combined latency and VSAMSql processing overhead exceed the allowed execution window. In such cases, using the local copy mechanism can help significantly reduce overall execution time.

8.8.2. Principle

The local copy mechanism consists of:

  • copying a VSAMSql file to a local VSAM before job execution,

  • executing the program using the local VSAM instead of the VSAMSql file,

  • synchronizing modified data back to the original VSAMSql file after execution.

The local VSAM is exclusive to the job for the entire duration of the step.

8.8.3. Process Description

Local copy initialization

Before the execution of the step:

  • the VSAMsql file is copied to a local file system,

  • a local VSAM is created on a specified volume,

  • exclusive access to this local VSAM is enforced.

Program Execution

During execution:

  • the program reads and writes data exclusively from the local VSAM,

  • no direct access to the VSAMSql file occurs.

Data Synchronization

After program completion:

  • the submit process synchronizes data back to the VSAMSql file,

  • synchronization behavior depends on the configured local copy mode.

8.8.4. Applicable Scenarios

The local copy mechanism applies to:

  • batch jobs with high VSAMSql access volume,

  • programs performing intensive read and write operations.

8.8.5. Usage Constraints

  • The local VSAM must be exclusive to the job.

  • The synchronization phase must complete successfully.

  • This mechanism is intended for batch processing only.

8.8.6. Practical Usage

File Identification

When a processing step exceeds its expected execution time, identify the VSAMSql files that are responsible for the slowdown.

Enabling Local Copy

To enable the local copy feature, add the following parameter to DD card configuration:

LOCALCOPY=<volume_name>

The specified volume should be located on a fast local file system.

Local Copy Mode

Add the following optional parameter:

LCPMODE=RAW | INC

RAW when specified, replaces the full content using IDCAMS REPRO REUSE.

INC compares the state of the local VSAM before and after execution, and reports all detected changes back to the original VSAM.

8.8.7. VSAMSql File Locking

Since all modifications are performed on a local copy of the file, it is recommended to lock the original VSAMSql file in order to prevent concurrent updates during program execution.

Allocating the file with DISP=OLD provides exclusive access, ensuring that no other process can update the VSAMSql file during execution and synchronization.

Using DISP=OLD maintains data integrity by avoiding situations where external processes introduce changes that would not be reflected in the local copy and could be overwritten or lost during the synchronization phase.

8.8.8. Summary

By using a local copy mechanism, batch jobs with high VSAMSql workload achieve reduced execution time while preserving data consistency and integrity

8.9. Profiling VSAMSql cache behavior

VSAMSql collects cache behavior statistics that can help identify performance issues and tune the cache parameters accordingly.

These statistics are logged in the log files when the logging level is set to INFO during batch job execution. For details on how to configure the logging level, refer to the LogLevel.

The information is logged to SYSOUT whenever a SQL commit is invoked, that is, when COMMITRATE is reached or when the program finishes execution.

A typical log entry looks like this:

[INFO] [VsamSqlProfiler]: ProgramReads=74, ProgramWrites=0, DBSelects=75, DBUpdates=0, DBInserts=0, DBDeletes=0, DBUnknown=0

In this example, the program sequentially reads 74 records (shown as ProgramReads) from a VSAM file. Since the prefetch cache size is set to 1, it actually performs 75 reads from the database (to account for internal operations needed by VSAMSql). If the prefetch cache is set to 100, the same program reduces database reads to just 4, as shown here:

[INFO] [VsamSqlProfiler]: ProgramReads=74, ProgramWrites=0, DBSelects=4, DBUpdates=0, DBInserts=0, DBDeletes=0, DBUnknown=0

8.10. Database isolation level

In some scenario, it is necessary to configure the isolation level (see here) of a process to a different level.

For example, consider a long-running batch job that updates data and you want to run online transactions (CICS) in parallel to read the same data. If the default isolation level is set to ReadCommitted, the batch job can lock rows or tables, preventing the online transactions from accessing the data. To avoid this, you can set the isolation level of the online transaction to Snapshot, allowing them to read the data without being blocked by the batch job.

In order to set the isolation level of a process, you need to configure an environment variable called: RC_VSAMSQL_ISOLATION_LEVEL.

The supported values are (see here):

  • Serializable

  • RepeatableRead

  • ReadCommitted

  • ReadUncommitted

  • Snapshot

  • Chaos

8.11. Command line options of VsamSql.load

Below are the details of the command line options of VsamSql.load.exe.

Load
Table 37. Details of command-line options for VsamSql.Load in category Load
Command-line option Default value Description

CatalogConfiguration

The catalog configuration file. If not set, use the default catalog

CodePage

The code page of the input data file. By default is the system code page

DataFile

Path to the file to be loaded

This argument is mandatory.

DeclDescriptors

An XML-based descriptors for the variable declarations as produced by the DeclDescriptors of the COBOL and PL/I compiler

FileId

The file id

OutputDirectory

Path to place the files for bcp

This argument is mandatory.

OutputFormat

Bcp

The output format Valid values are:

  • Bcp

  • Insert

  • PsqlCopy

  • PsqlInsert

PartitionNumber

0

The partition in which the data must be loaded

RecordFormat

Unknown

The record format of the file, if the file doesn’t exist. Accepted values = Unknown, FB, VB, FBA, VBA

RecordLength

The record length of the file, if the file doesn’t exist

Struct

the name of a variable of DeclDescriptors used to define the columns

TableName

The table’s name in which the data should be loaded

TargetDsn

The DSN in which the data must be loaded. It must be prefixed by the volume, for ex ":DEFALT:MY.DSN.FILE"

This argument is mandatory.

Miscellaneous
Table 38. Details of command-line options for VsamSql.Load in category Miscellaneous
Command-line option Default value Description

DotNetConfigFile

This command-line option is an additional .net 'app.config' file.

Help

Displays the tool’s help information.

IgnoreUnkownArgs

Info

False

Displays a description of the program.

LogLevel

WARNING

Specifies the log level. Valid values are:

  • SILENT

  • ERROR

  • WARNING

  • PROGRAM_OUTPUT

  • PROGRAM

  • INFO

  • DEBUG

  • TRACE

  • DIAGNOSTIC

Version

False

Displays the version information.

8.12. Command line options of VsamSql.DbGenerator

Below are the details of the command line options of VsamSql.DbGenerator.exe.

Generation
Table 39. Details of command-line options for VsamSql.DbGenerator in category Generation
Command-line option Default value Description

CatalogConfiguration

The input catalog configuration file for generating the database scripts. If not set, use the default catalog

DeclDescriptors

An XML-based descriptors for the variable declarations as produced by the DeclDescriptors of the COBOL and PL/I compiler

OutputFile

./vsamsql.sql

The output file (.sql). If catalog configuration contains more than one connection plan. One file is created by plan and the file is suffixed by the plan name

SqlDatabase

The connection string to the database to check if the tables already exists.

Struct

the name of a variable of DeclDescriptors used to define the columns

TableName

the name table for which the creation script should be generated

TargetDbType

SQLSERVER

The target database type Valid values are:

  • SQLSERVER

  • SQLITE

  • POSTGRESQL

Miscellaneous
Table 40. Details of command-line options for VsamSql.DbGenerator in category Miscellaneous
Command-line option Default value Description

DotNetConfigFile

This command-line option is an additional .net 'app.config' file.

Help

Displays the tool’s help information.

IgnoreUnkownArgs

Info

False

Displays a description of the program.

LogLevel

WARNING

Specifies the log level. Valid values are:

  • SILENT

  • ERROR

  • WARNING

  • PROGRAM_OUTPUT

  • PROGRAM

  • INFO

  • DEBUG

  • TRACE

  • DIAGNOSTIC

Version

False

Displays the version information.

Plugin
Table 41. Details of command-line options for VsamSql.DbGenerator in category Plugin
Command-line option Description

Plugin

The list of plugins to be loaded when the tool executes.

PluginPath

This command-line option specifies the path to plugins that are searched.

9. JclConversion

JclConversion is a functionality that converts JCL into a new format, typically such that the converted JCL uses a different utility than what was originally specified in PGM. To activate this functionality, the option JclConverter of Submit is used.

In itself, JclConversion does not perform the conversion; instead, it delegates the core of this work to external programs. These programs are not meant to be written by the user, they are supplied by Raincode. The converted output is placed in an output directory, as specified by the configuration file discussed below.

The result of a conversion is not automatically used by Submit in future calls of the JCL. Instead, it is the responsibility of the user to ensure that the converted JCL, which has been placed in the output directory, is used where appropriate.

9.1. JclConverter config file

The JclConverter config file is an XML file that describes which PGM= must be converted and how to convert them. An example file is below, and it specifies that calls to SORT need to be replaced with calls to SYNCSORT and that the SYSIN DD needs to be converted by the XSORT conversion program.

<JclConverterInfo
  JclConvSaveDir="outputDir">
  <JclConverterPGMs>
    <JclConverterPGM
      PGM_ConvScript="XSORT"
      PGM_ConvDD="SYSIN"
      PGM_ConvExeCur="SORT"
      PGM_ConvExeNew="SYNCSORT" />
  </JclConverterPGMs>
</JclConverterInfo>

There is one JclConverterPGM element for each PGM to be converted. The meaning of the different attributes are:

XML Attribute

Description

JclConvSaveDir

Defines where the new JCL will be saved with the same name as the original one

PGM_ConvExeCur

The name of the PGM to match on

PGM_ConvExeNew

The new name of the PGM, after conversion

PGM_ConvDD

DD name with the input that will be converted into the new syntax by the conversion program. This DD will have the new commands in the newly created JCL

PGM_ConvScript

The script that will perform the conversion

If the converted JCL already exists in the JclConvSaveDir, this file will be overwritten.
The JCLConverter supports only inline DD for the parameter PGM ConvDD, as it will place the result of conversion there.

Below are the three sample JclConverterPGM elements.

Sample 1: JclConverterPGM to convert a SORT step

<JclConverterPGM
 PGM_ConvScript="XICETOOL"
 PGM_ConvDD="TOOLIN"
 PGM_ConvExeCur="ICETOOL"
 PGM_ConvExeNew="XXXTOOL" />

Sample 2: JCLConverterPGM to convert Db2 LOAD/UNLOAD (DSNUTILB) step

<JclConverterPGM
 PGM_ConvScript="XDSNUTILB"
 PGM_ConvDD="SYSIN"
 PGM_ConvExeCur="DSNUTILB"
 PGM_ConvExeNew="RCDSNUTILB" />

Sample 3: JCLConverterPGM to convert HPU UNLOAD (INZUTILB) step

<JclConverterPGM
 PGM_ConvScript="XINZUTILB"
 PGM_ConvDD="SYSIN"
 PGM_ConvExeCur="INZUTILB"
 PGM_ConvExeNew="RCINZUTILB" />

9.2. Considerations for JCLConverter

The use of the JCLConverter has the following prerequisites:

  • The translation tools must be installed with the Raincode Stack.

  • The JCL to be converted must be executed in a working environment where the file catalog is available; files defined in JCL will be accessed within this JCL run.

  • Files will be created or updated depending on the use of their DD statements in the JCL, just like a normal execution.

  • RestartJobID can not be used.

In the case of a Sort SYSIN or ICETOOL TOOLIN to be converted into multiple steps (SYSINs and TOOLINs), the following changes to the JCL will apply:

  • The JCL, will have SYSIN1 to SYSINn depending on the generated SYSINs from the SortTranslator for SORT or ICETOOL.

  • For the SORT, the EXEC PGM statement will get an additional parameter for the execution:

PARM='SYSIN=n,TEMP=n'

where SYSIN=n, is the number of SYSINs and TEMP=n is the number of used temporary files of the SYNCSORT execution.

For the ICETOOL, the EXEC PGM statement will get an additional parameter for the execution:

PARM='TOOLIN=n,TEMP=n'

where TOOLIN=n is the number of TOOLINs and TEMP=n is the number of used temporary files of the Syncsort execution.

  • The PowerShell script Syncsort or ICETOOL will read these parameters and execute the SYNCSORT/ICETOOL.exe as required.

  • All used $ENV:DD_variables will be replaced in this PowerShell script. The DD_TMP files will be in the SYSLOG directory of the given JOB.

9.3. Sample Sort

9.3.1. Input

//STEP03   EXEC PGM=SORT

//SYSIN    DD   *
SORT FIELDS=(1,12,CH,A)
/*

9.3.2. Output

Below is the output produced from the SORT command: submit -Jclconverter="c:\convertedJcl.xml"

//STEP03   EXEC PGM=SYNCSORT

//SYSIN    DD   *
/FIELDS Src_0 1 12 CHARACTER
/INFILE $env:DD_SORTIN FIXED 80
/KEYS Src_0 ASCENDING
/COLLATINGSEQUENCE DEFAULT EBCDIC
/OUTFILE $env:DD_SORTOUT FIXED 80 OVERWRITE
/*
Environment variables $env:DD_SORTIN etc. will be replaced with the actual content at execution before the SYNCSORT is called.

9.4. Sample SORT for multiple SYSIN files

9.4.1. Input

//STEP02   EXEC PGM=XSORT
//SYSIN    DD   *
  JOINKEYS F1=INPUT1,FIELDS=(3,4,A,7,4,A)
  JOINKEYS F2=INPUT2,FIELDS=(1,4,A,5,4,A)
  JOIN UNPAIRED,F1,ONLY
  SORT FIELDS=(3,20,CH,A,68,10,ZD,A)
/*
//*       END

9.4.2. Output

//STEP02   EXEC PGM=SYNCSORT,PARM='SYSIN=4,TEMP=3'
//SYSIN1   DD   *
/FIELDS Src_0 3 4 UINTEGER BIGENDIAN, Src_1 7 4 UINTEGER BIGENDIAN
/INFILE $env:DD_INPUT1 STREAM CRLF
/KEYS Src_0 ASCENDING, Src_1 ASCENDING
/COLLATINGSEQUENCE DEFAULT EBCDIC
/OUTFILE $env:DD__TMP1 STREAM CRLF OVERWRITE
/END
/*
//SYSIN2   DD   *
/FIELDS Src_0 1 4 UINTEGER BIGENDIAN, Src_1 5 4 UINTEGER BIGENDIAN
/INFILE $env:DD_INPUT2 STREAM CRLF
/KEYS Src_0 ASCENDING, Src_1 ASCENDING
/COLLATINGSEQUENCE DEFAULT EBCDIC
/OUTFILE  $env:DD__TMP2 STREAM CRLF OVERWRITE
/END
/*
//SYSIN3   DD   *
/FIELDS Src_2 1 4, Src_3 5 4
/FIELDS Src_0 3 4, Src_1 7 4
/INFILE  $env:DD__TMP1 VARIABLE 80
/JOINKEYS SORTED Src_0, Src_1
/INFILE  $env:DD__TMP2 VARIABLE 80
/JOINKEYS SORTED Src_2, Src_3
/JOIN UNPAIRED LEFTSIDE ONLY
/OUTFILE  $env:DD__TMP3 VARIABLE 152 OVERWRITE
/END
/*
//SYSIN4   DD   *
/FIELDS Src_0 3 20 CHARACTER, Src_1 68 10 ZD
/INFILE  $env:DD__TMP3 VARIABLE 152
/KEYS Src_0 ASCENDING, Src_1 ASCENDING
/COLLATINGSEQUENCE DEFAULT EBCDIC
/OUTFILE $env:DD_SORTOUT FIXED 80 OVERWRITE
/END
/*
//*       END

9.5. Possible error messages

  • JclConverter JclConvDD is not set

  • JclConverter JclConvExeCur is not set

  • JclConverter JclConvExeNew is not set

  • JclConverter JclConvPgmName not found as an EXE in this JCL

  • JclConverter JclConvSaveDir must be different from jclFilePath

  • JclConverter JclConvSaveDir is not set or empty

  • JclConverter JclConvScript is not set

  • JclConverter JclConverterPgms is not set or empty

  • JclConverter JclConverterXML file not found or error

  • JclConverter JclFilePath not set. Have to abend, Submit must be called with a file parameter

  • JclConverter RestartJobID must not be used if JclConvert is used

10. JCL Error codes

Raincode JCL introduces a few Return codes, as mentioned in this section.

Table 42. System completion Error codes

Error codes

Description

RC016Error = 16

Error return code value to be used to determine if a higher return code should be set in a certain error condition.

RC020OutOfMemory = 20

The return code of the process when it is out of memory due to a REGION parameter violation.

RC08DefaultJobSkipped = 8

Default return code when ShouldRun indicates the job should not run.

RC021NStepSkipped = 21

STEP was skipped by condition

RC027NPgmNotFound = 27

PGM not found when CONTROLM is set, report error -27 and continue. Also, refer to RCS806PgmNotFound = 806

Table 43. System Abends, internal +8192, and throw messages
Error codes Description

RCS097DCBError = 97

DCB argument Error

RCS098ArgError = 98

Argument exception error

RCS099DefaultAbend = 99

The default ABEND return code when triggered by error conditions controlled by batch - not used for program ABENDs

RCS122 = 122+8192

CTRL = C abend S122

RCS801 = 801

JCL Error Dataset already exists

RCS802 = 802

Access error PDS Member

RCS806PgmNotFound = 806

PGM not found abend S806 when CONTROLM is not set issue this error and stop processing

RC875ProcError = 875

The default return code for PROC must be different when correctly set in all cases

RC876StepError = 876

The default return code for STEP must be different when correctly set in all cases

RC987JobError = 987

The default return code for JOB must be different when correctly set in all cases

RCS901JclNoStep = 901

JCL ERROR JOB NOT RUN - JCL ERROR JOB HAS NO STEPS

RCS902JclErrorDSN = 902

Invalid dataset name specified

RCS903JclErrorDISP = 903

Invalid DISP=SHR IEF286I DISP FIELD INCOMPATIBLE WITH DSNAME

RCS904SDSN_Wait = 904

SDSN_WAIT Abend Timer

RCS905NoStepExe = 905

No steps have been executed for this job

RCS906DDError = 906

Non existent GDG or PDS

RCS907DCBError = 907

Conflicting DCB Parameters

RCS949DSNMeta = 949

DSN Metadata file missing or corrupt

RCS950DSNDup = 950

DSN duplicate already exiting

RCS951JclConvert = 951

JclConverter Error see the message

RCS996Error = 996

Error in the STEP StartTime/EndTime maybe some fields are not set correctly

RCS998Error = 998

Return code for SUBMIT Return code not handled somewhere else

RCS999SubmitError = 999

Return code for Submit to return if an internal error occurs

RCS9000 = 9000

Rclrun error 9000 - 8192 = S808

RCS9080 = 9080

Abend by compiler COBOL / PLI / HLASM 9080 - 8192 = S888

RCS9081 = 9081

Command line parsing error 9081 - 8192 = S889

RCReturnCodeMask = 0x0FFF

RCUserAbendMask = 0x1000

RCSystemAbendMask = 0x2000

Part II: Development

11. Submit For Developers

Some elements of Submit are targeted towards developers, so they are presented in this section.

11.1. Environment variables defined by Submit

For each step that is executed, Submit defines several environment variables, which are available to the program that is executed during that step.

Table 44. Environment variables defined by Submit
Environment Variable Description

RC_JOB_ID

Contains the value of the option JobID. See section Command-line options for Submit.exe.

RC_STEP_ID

Current executing StepID

RC_JOB_NAME

Current executing Job Name

RC_LegacyRunner

Legacy runner path for COBOL, PL/I, Assembler DLL. The default value is $(RCDIR)/bin/rclrun.exe.

RCBATCHDIR

Path to Raincode JCL binary from where Submit.exe was started.

RC_DB_CONNECTION

connection string defined. Utilities like IKJEFT01 may overwrite this.

RC_DB_TYPE

DB Type associated with the connection String

RC_JOB_RESTARTED_ID

Contains the value of the option RestartJobID. See section Command-line options for Submit.exe.

…​ < From Raincode.Catalog.xml >

All Environment variables defined in Raincode.Catalog.xml match the conditions. For more details, see Environment Variables.

In addition to the above, Submit defines environment variables for each DD that it treats when executing a JCL step. These start with DD and end with the name of the DD, as shown in the table below.

Table 45. DD environment variables defined by Submit
Environment Variable Description

DD_<name>

The path to the file, or a semicolon-separated list when there are multiple.

DDDISP_<name>

The disposition of the DD.

DDLRECL_<name>

The Record Length.

DDRECFM_<name>

The Record Format.

DDMETAKEEP_<name>

Flag whether to keep the meta file or not.

DDMETA_<name>

The path to the meta file, when kept.

DDPARAM_<name>

Extra driver parameters.

11.2. Debugging batch jobs

To enable the debugging of the execution of a JCL, i.e. a batch job, Submit includes the ability to increase execution trace information, as well as to use the .Net SDK debugger.

11.2.1. Increasing log information: use Trace

Increase the LogLevel to increase details in the log messages produced by the execution of the program. -LogLevel=TRACE provides very detailed information on what Submit is doing. Add -LogToConsole to output logs to the console instead of MSGLOG.txt.

11.2.2. Debug at .Net Level

If the Trace logs do not help, you may consider debugging a batch job at the .Net level. This, of course, presupposes that the full SDK is installed. Two levels of debugging are possible: the job level and the step level.

Debug Job

Running submit with the -DebugSubmit=true flag will cause execution to break before any steps are executed. An SDK debugger window will pop up and open. Select the source code you wish to debug and attach the debugger. The breakpoint will hit when the source is executed for any of the steps.

Debug Step

Running Submit with the -DebugStep=STEPNAME will cause the execution to break just before the given step. An SDK debugger window will pop up and open. Select the source code for the step executable to debug and attach the debugger.

11.3. Timeshift

Timeshift testing is needed to test how a job behaves in the future or the past. The Raincode legacy runtime provides a way to perform Timeshift testing by letting you modify the date and time retrieved by the job when executing.

Timeshift can be:

  • absolute by defining an initial date and time for the run or

  • relative by defining a date time offset relative to the current time.

If RC_DATETIMEOFFSET is defined (in the format of C# TimeSpan), this offset is added to DateTime.Now when the Date/Time is read by all the steps.

If RC_DATETIMEOFFSET is not defined, the runtime checks (only once) the environment variable RC_INITIALDATETIME.

Suppose RC_INITIALDATETIME is defined (in the format of C# DateTime). In that case, the runtime computes the DateTime offset between now and the provided value and sets the RC_DATETIMEOFFSET environment variable to ensure that the called program/step uses the same offset.

Submit program accepts the command line parameter -InitialDateTime to set up the Initial DateTime/offsets.

These rules and environment variables also apply to Raincode legacy stack runtime. For more details, refer to Timeshift.

12. Plugins

12.1. Introduction

To support an extensible and customisable system that adapts to client’s needs, Raincode has a plugin system that pervades the entire toolset. This section presents the plugin mechanism for plugin implementers.

In terminology:

  • A plugin is a piece of software that adds specific functionality to the toolset without altering its core.

  • A plugin hook is the specific point in the toolset’s execution where the toolset calls the plugin.

  • The entry point is the method that receives the initial call to the plugin hook.

A hook calls its plugin according to the API that is defined for that specific kind of plugin. This API can be typed using an interface or an abstract class; i.e., a plugin implements that interface or abstract class. All hooks have a default plugin attached and include a strategy on how to decide which plugin to call at runtime. These strategies are defined later in this document, in Entry Point Strategies.

A plugin is provided as a dll. To load a plugin in a certain tool, use the argument -Plugin, or -PluginPath, or drop the plugin assembly in the default plugin path for the tool (which is documented on a tool-by-tool basis).

12.2. Implementing a Plugin

Plugins are at the heart of the Raincode toolset, conceptually and in practice: the mechanism is defined in Raincode.Core.Plugin namespace inside of the rccorelib library, i.e. in the core library of the toolset. There are two different kinds of plugins:

  • Action plugins are plugins that perform a single action and do not hold any state nor return any value when the action is triggered, i.e. the entry point of the plugin is a method with a void return type.

  • Normal plugins are plugins with a possibly more complex API. The entry point of the plugin returns a value that is of the type expected by the hook. The hook will then use this value according to the declared API.

Some more terminology: a bootstrap function is a function of the plugin that is called at startup of the runtime, and is responsible for registering the plugin with its hook (after initialization, if needed).
Bootstrapping a plugin

The assembly of the plugin needs to inform the runtime of its bootstrap function, so that this bootstrap function can be called when the runtime is initialized. To do this, an assembly attribute of the following form needs to be added:

[assembly:PluginProvider(typeof(NameSpace.To.Plugin.Plugin),"BootstrapPlugin")]

where the first parameter (NameSpace.To.Plugin.Plugin) is the type of the class of the plugin, and the BootstrapPlugin static method named in the second parameter is the bootstrap function of the plugin.

The Raincode tools will call the BootstrapPlugin static method right after loading the assembly. This method should then perform intialization, if needed, and register itself with the correct hook. To do the latter, it calls the static Provide method of the intended plugin hook. For example, in the case of creating a Qix Factory plugin, this would be:

RaincodeLegacyQixInterface.QixInstances.QixFactory.ConstructorPlugin.Provide(priority, delegateMethod)

The Provide method takes two parameters: a priority value and a .NET delegate type (i.e. a method signature) for the entry point of the plugin. The priority is used in the entry point strategy of the hook. Each hook will have its own type of delegate, i.e. its own type for the entry point of the plugin. Documentation of the types of hooks and the signature of the entry point is explained in the Plugin hook section.

Calling of Plugins

From this point on, whenever a hook needs a plugin it will call the appropriate registered entry point, as defined by its Entry Point Strategy.

Depending on the type of plugin hook, the entry point method receives different types of arguments. The types and values used by the plugin hooks are described (semi-formally) in their corresponding sections of the documentation, and the plugin hook section explains how to read these descriptions.

To continue the QixFactory example, a possible entry point is the following Builder method, which simply instantiates a new factory with the given QIX context:


public static QixFactory Builder(IQixContext context){
    return new MyQixFactory(context);
}

Once a QixFactory has been initialized in this way, the methods on this object will be called according to the API for the plugin (as explained in the plugin hook section).

12.3. Examples

This section provides a few example plugins to illustrate various features of the plugin mechanism.

Action Plugin: Execution Context Preparing

This plugin is called after an execution context has been initialized. It gets as arguments the newly initialized context and the name of the entry point of the called COBOL or PL/I code.

The example implementation below simply adds an informational line to the log in the PostInit method. This method is registered as an entry point in the Register method, and the assembly properties declare this class as a plugin with the Register method as the bootstrap function.

[assembly: PluginProvider(typeof(MyExtraLog.ExCPLogger), "Register")]

namespace ExCPLoggerNS
{
    public class ExCPLogger
    {
        public static void Register()
        {
            ExecutionContext.PreparePlugin.Provide(100, PostInit);
        }

        private static LogSource src = new LogSource("Ctx prep logger");

        public static void PostInit(ExecutionContext ctx, string entry)
        {
           Logger.LogInfo(src, $"New context created for entry point {entry}");
        }
    }
}
Password rewriter

The password rewriter plugin serves as an example of a basic plugin: the entry point receives a connection string and should return a connection string with the password rewritten to the required value. The hook for the password rewriter is present throughout the toolset. Basically, everywhere a connection string is used, this plugin will be called before the connection is made.

The example below shows such a password rewriter plugin. It replaces !PASSWORD! with a hard-coded value, as can be seen in the body of the MapPassword method.

[assembly: PluginProvider(
    typeof(OwnPasswordRewriter.OwnPasswordRewriterSample),
    "Register")]
namespace OwnPasswordRewriter
{
    public class OwnPasswordRewriterSample
    {
        public static void Register()
        {
            RainCodeLegacyRuntimeUtils.PasswordMapping.PasswordRewriter.Provide(10, MapPassword);
        }

        private static string MapPassword(string connectionString)
        {
            return  connectionString.Replace ("!PASSWORD!", "myNoLongerSecretPassword");
        }
    }

}
DumpProcessor

The DumpProcessor plugin is an example plugin that shows the use of a more complex API: the entry point should create an instance of BaseDumpProcessor, and this will later be tasked to provide functionality for specific parts of a program dump.

The example below shows how the entry point simply returns an instance of the MyDumper class. Then the different method implementations of the abstract methods declared in BaseDumpProcessor take care of producing an XML document for the dump. Note the Exception method; it gets the underlying runtime exception triggered by the faulty code. This illustrates how (deeply) internal elements can be exposed to plugins, to be treated as required by the plugin.

[assembly: PluginProvider(typeof(DumpProcessPlugin.MyDumper), "RegisterMyDumper")]

namespace DumpProcessPlugin
{
    public class MyDumper : BaseDumpProcessor
    {
        const string FILENAME = "dump.xml";
        XDocument doc;
        Stack<XElement> elems;

        public static void RegisterMyDumper()
        {
            ConstructorPlugin.Provide(10, NewDumper);
        }

        public static MyDumper NewDumper(ExecutionContext ctx)
        {
            return new MyDumper();
        }

        public override void Start()
        {
            doc = new XDocument();
            elems = new Stack<XElement>();
            doc.Add(new XElement("dump"));
            elems.Push(doc.Root);
        }
        public override void End()
        {
            doc.Save(FILENAME);
        }
        public override void Exception(Exception e)
        {
            doc.Root.Add(new XElement("exception", e.Message));
        }
        public override void CurrentStatement(string position)
        {
            doc.Root.Add(new XElement("position", position));
        }
[...]
    }
}
DB connection plugin

Some use cases require sending specific commands to the DB when opening or closing a database connection. To allow for this, Raincode JCL lets you implement a C# plugin that will be called just after the call of Open function and just before the call of Close. It will be given the instance of System.Data.Common.DbConnection that represents the connection.

Sample Plugin implementation
using System;
using System.Data.Common;
using RainCode.Core.Logging;
using RainCode.Core.Plugin;

[assembly: PluginProvider(typeof(Raincode.Tests.DbConnectionPlugin), nameof(Raincode.Tests.DbConnectionPlugin.Register))]
namespace Raincode.Tests
{
    public class DbConnectionPlugin
    {
        private static LogSource LogSource = new LogSource("DbConnectionPlugin");
        public static void Register()
        {
            Logger.LogInfo(LogSource, "Registering QueryTranslation");
            Raincode.Batch.Utilities.Database.DatabaseConnection.BatchSQLConnectionCreate.Provide(10, ConnectionCreate);
            Raincode.Batch.Utilities.Database.DatabaseConnection.BatchSQLConnected.Provide(10, ConnectionOpen);
            Raincode.Batch.Utilities.Database.DatabaseConnection.BatchSQLDisconnect.Provide(10, ConnectionClose);
        }

        private static DbConnection ConnectionCreate(DbConnection arg)
        {
            // manage the connection after create and before open
            Console.WriteLine("ConnectionCreate");
            return arg;
        }

        private static DbConnection ConnectionOpen(DbConnection arg)
        {
            // manage the connection after open
            Console.WriteLine("ConnectionOpen");
            return arg;
        }

        private static DbConnection ConnectionClose(DbConnection arg)
        {
            // manage the connection Before close
            Console.WriteLine("ConnectionClose");
            return arg;
        }
    }
}
Custom Plan Mapping

In some situations, the dbConnectionDataProvider file (see Map a PLAN name to a connection string) will be insufficient to map a PLAN name to the actual connection string.

To address that limitation, Raincode JCL lets you implement a C# plugin that implements a custom mapping scheme. It is called right after the resolution of the PLAN name with two parameters:

  1. The PLAN Name

  2. Then proposed connection string, as resolved by Submit.

It returns a string, which is the connection string that will be used.

Example uses for this plugin are:

  1. Implementing a custom PLAN to connection string mapping

  2. Retrieving a password and patch the connection string with the actual password to use

Sample plugin implementation

A sample for the C# plugin: DbConnectionMapperSample is available in the samples directory in the Raincode JCL installation directory. The code of this sample is as follows:

using RainCode.Core.Plugin;
using System;

[assembly: PluginProvider(typeof(DbConnectionMapperSample.DbConnectionMapperPasswordSample), nameof(DbConnectionMapperSample.DbConnectionMapperPasswordSample.Register))]
namespace DbConnectionMapperSample
{
     public class DbConnectionMapperPasswordSample
     {
         public static void Register()
         {
             Raincode.Batch.Common.DbConnectionDataProvider.ConnectionMappingPlugin.Provide(10, MapPassword);
         }

         private static string MapPassword(string plan, String proposed_connectionString)
         {
             /* Here retrieve the connection string */
             /* return null if no patch is possible                    */
             if (plan == "test")
               return  = "Your special connection string";
             else return proposed_connectionString;
         }
     }
}
Password Plugin

Another problem with the dbConnection provider file (see Map a PLAN name to a connection string) is that the file storing the connection strings will contain passwords in plaintext.

To address this limitation, Raincode JCL lets you implement a C# plugin that will be called just before executing the connection call to the database layer. Its purpose is to retrieve the actual password, and as this is called at the latest moment, the actual connection string (including the password) will not appear in any log file.

The basic usage scheme is to create a dbConnection provider file (or a custom plan mapping plugin) that stores the full connection string where the password is a pattern that is easy to match. These patterns will then be replaced at the latest moment by the actual password retrieved via your security process in the plugin.

If used please ensure to add -Plugin=<assembly> -PluginPath=<path> in your custom rclrun.args file and add these to .args files to batch utilities that would need to connect the database (like DNSUTILB, …​).

Sample Plugin implementation

A sample implementation of this plugin is as follows:

using RainCode.Core.Plugin;
using RainCodeLegacyRuntimeUtils;

[assembly: PluginProvider(typeof(OwnPasswordRewriter.OwnPasswordRewriterSample), nameof(OwnPasswordRewriter.OwnPasswordRewriterSample.Register))]
namespace OwnPasswordRewriter
{
    public class OwnPasswordRewriterSample
    {
        public static void Register()
        {
            RainCodeLegacyRuntimeUtils.PasswordMapping.PasswordRewriter.Provide(10, MapPassword);
        }

        private static string MapPassword(string connectionString)
        {
            /* Here patch the connection string with correct password */
            /* return null if no patch is possible                    */
            string res = connectionString.Replace ("#PASSWORD#", "myPassword");
            return res;
        }
    }

}
Custom Interface Configurations

The behavior of Raincode JCL can also be customized programmatically by providing C# implementations of a number of interfaces.

The default application configuration is located in the installation directory, submit.exe.config. The JCL runtime uses Autofac to register types for the various interfaces that are supported.

Raincode.Batch.Runtime.IExecutionController
  • This interface is called before and after steps, and jobs are executed.

  • This interface is useful to implement if custom logging, tracing, or individual step inspection is required.

  • The submit.exe.config contains the registration for the DefaultExecutionController, which does nothing.

  • Replace the class specified in the <autofac>/<components>/<component> element for IExecutionController to register a custom class. (e.g., <component type="Raincode.Batch.Runtime.DefaultExecutionController,Raincode.Batch.Runtime" service="Raincode.Batch.Runtime.IExecutionController,Raincode.Batch.Runtime">)

Raincode.Batch.Jcl.Interfaces.IJclPreprocessor
  • This interface is called before and after AutoEdit variables are replaced in the input stream, and called to set/modify/update the SUBSTVAR dictionary variables.

  • The submit.exe.config contains the registration for the DefaultPreProcessor, which does nothing.

  • Replace the class specified for IJclPreprocessor to register a custom class.(e.g., <component type = "Raincode.Batch.Jcl.DefaultPreProcessor,Raincode.Batch.Jcl" service= "Raincode.Batch.Jcl.Interfaces.IJclPreprocessor,Raincode.Batch.Jcl">;)

Raincode.Batch.Runtime.IExecuteSecurity
  • This interface is called to determine if a user can run a job, submit a particular dataset, or submit a particular file.

  • It operates independently of standard Windows security ACLs that can be set on volumes/files.

  • The submit.exe.config contains the registration for the DefaultExecuteSecurity class, which returns true for each of the methods allowing any job or dataset to be submitted.

  • Replace the class specified for the IExecuteSecurity service in the submit.exe.config file with a custom class.(e.g., <component type="Raincode.Batch.Runtime.DefaultExecuteSecurity,Raincode.Batch.Runtime" service="Raincode.Batch.Runtime.IExecuteSecurity,Raincode.Batch.Runtime">;)

Raincode.Batch.Runtime.IPrintHandler
  • This interface is called to control the spooling of outputs to a printer/file/other destination.

  • This element uses the name attribute to specify the name of the output class to map to the custom print handler.

  • There are three separate print handlers that are provided, which are documented in the submit.exe.config file. (e.g., <component type="Raincode.Batch.Runtime.DefaultPrintHandler,Raincode.Batch.Runtime" service="Raincode.Batch.Runtime.IPrintHandler, Raincode.Batch.Runtime" name="A">; Registers the default print handler (will print to the default printer on the machine for output class A. )

  • When a SYSOUT item is spooled with the default print handler, it will read the ASA control character and advance the appropriate number of lines/pages before writing the output.

UserWaitForFilePlugin

A sample code snippet is provided below:

Registration of the plugin: DataSetMetaPersistenceFile.UserWaitForFilePlugin.Provide(10, OwnWaitForFile);

        internal static int waitcount = 0;
        internal static string lastname = "";
        // return True =  try to read again
        // return False = continue with the status file not found
        private static bool OwnWaitForFile(string Fullpath, FileMode fmode, FileAccess faccess, Exception ex)
        {
        //check for file with the name ZFMGTE\\#0001 and retry two times
            if (lastname != Fullpath)
            {
                lastname = Fullpath;
                waitcount = 0;
            }
            if (Fullpath.Contains("ZFMGTE\\#0001"))
            {
                if (waitcount >= 2)
                    return false;
                waitcount++;
                return true;
            }
            return false;  // This is the default
         }

12.4. Global Plugins Settings

Some plugins are required across all Raincode tools.

A common example is a Password Plugin, which may be needed for every application and tool.

You can define two environment variables to configure plugins that will be automatically loaded by the runtime, as mentioned below:

RC_DEFAULT_PLUGIN

RC_DEFAULT_PLUGIN = plugin1;plugin2,param2;..

Format:

pluginName1[,parameter1][;pluginName2[,parameter2]…​]

  • Plugins names are separated by a semicolon (;).

  • Specify the plugin name without the .dll extension.

  • Optional parameters can be provided after a comma.

RC_DEFAULT_PLUGIN_PATH

RC_DEFAULT_PLUGIN_PATH = path1;path2;…​

Format:

path1[;path2…​]

  • Paths are separated by a semicolon (;).

  • These paths define where the runtime will look for plugin binaries (.dll files).

This feature is available in version 5 starting from 5.0.399, and in version 6 starting from 6.0.33.

13. Raincode Plugins

13.1. Plugin Hook Documentation

There are many plugin hooks present in the Raincode toolset, and they are described at the relevant locations throughout the documentation. To better understand these descriptions, the following text is included at each location.

Generated Hook Descriptions

Descriptions of the Raincode Plugin hooks are automatically generated, based on annotations made in the source code of the hooks. This section explains how to interpret those descriptions.

The generated documentation can include up to three parts: the hook description (mandatory), the plugin API documentation (optional), and the plugin description (optional).

The hook class description

This is a table that contains up to three rows:

  1. Field/Property with hook object: The location of the hook.

  2. Default implementation: describes the behavior of the default plugin in plain text.

  3. Strategy: the kind of entry point strategy (for more details, refer to Entry Point Strategies).

Plugin API

This reveals at a minimum the root of the API specification of the plugin: the signature of the entry point of the plugin.

Apart from this signature, the API section may also contain a textual description of the characteristics of the API, e.g. describing the roles of the different methods in the returnType.

Plugin Description

This is a (brief) textual description of what the intended functionality of the plugin is.

Entry Point Strategies

When a plugin hook encounters multiple registered plugins, a decision is made on which of these plugins is (the most) suitable. The hook is hard-coded to use a specific strategy to make this choice. To clarify the meaning of these strategies, they are documented here.

Strategies are subclasses of the RainCode.Core.Plugin.Strategy class, and there are multiple strategies defined out-of-the-box:

  • Strategy.Best: This is the default strategy for plugins that return a result. This strategy only calls the highest priority implementation.

  • Strategy.ExecAll: This is the default strategy for action plugins. It calls all the implementations by decreasing priority.

  • Strategy.BestNonNull<R>: This calls entry points by decreasing priority until a non-null result is found. The return type of the entry point must be a class or interface.

  • Strategy.BestWithValue<R>: This calls entry points by decreasing priority until HasValue on the return value is true. The return type of the entry point must be a nullable value type.

  • Strategy.All: This calls entry points by decreasing priority until false is returned.

  • Strategy.Any: This calls entry points by decreasing priority until true is returned.

The priority of the default plugins is zero.

13.2. List of Raincode Plugins

13.2.1. IdcamsDelete

Class

Raincode.Batch.Utilities.Idcams.DeleteStatement

Field name

IdcamsDeletePlugin

Strategy

Best

Default implementation

The default implementation doesn’t change the DeleteParams

Plugin API:

Raincode.Batch.Utilities.Idcams.DeleteParams(Raincode.Batch.Utilities.Idcams.DeleteParams params)

  • params

Description:

Allows to modify DeleteParams structure. For example set Dirdel to true to delete the directory instead of each file for the pattern "name.*". An example can be found in test case Raincode.Tests.Idcams.RutimeTestsIdcams_Internal.RCO_1157286726_DELETE_DIR_PLUGIN

13.2.2. UserCommentBuilder

Class

Raincode.Batch.Runtime.Executable

Field name

UserCommentBuilderPlugin

Strategy

Best non null

Plugin API:

string(Raincode.Batch.Runtime.Step arg0 ,string arg1)

Description:

Build custom comment string. This string is passed as -Comment=”xxx” to Cobol program

13.2.3. SaveJCLListing

Class

Raincode.Batch.Runtime.JobPersistence

Field name

SaveJCLListingPlugin

Strategy

Best

Default implementation

The basic implementation save on file in Job Sysout folder

Plugin API:

string(RainCodeLegacyBatchCatalog.Manager arg0 ,string arg1 ,string arg2 ,System.Collections.Generic.List<string> arg3)

Description:

Save the listing of the actual JCL (proc expanded, etc).

13.2.4. ReadSavedJCLListing

Class

Raincode.Batch.Runtime.JobPersistence

Field name

ReadSavedJCLListingPlugin

Strategy

Best

Default implementation

The basic implementation read from file in Job Sysout folder

Plugin API:

System.Collections.Generic.List<string>(RainCodeLegacyBatchCatalog.Manager arg0 ,string arg1 ,string arg2)

Description:

Read the listing of the the restarted job.

13.2.5. SaveJobState

Class

Raincode.Batch.Runtime.JobPersistence

Field name

SaveJobStatePlugin

Strategy

Best

Default implementation

The basic implementation save on file in Job Sysout folder

Plugin API:

bool(RainCodeLegacyBatchCatalog.Manager arg0 ,string arg1 ,string arg2 ,string arg3)

Description:

Save the json image of the current job status. Used for restart and saved between every step.

13.2.6. ReadSavedJobState

Class

Raincode.Batch.Runtime.JobPersistence

Field name

ReadSavedJobStatePlugin

Strategy

Best

Default implementation

The basic implementation read from file in Job Sysout folder

Plugin API:

string(RainCodeLegacyBatchCatalog.Manager arg0 ,string arg1 ,string arg2)

Description:

Read the json image of the restart job status.

13.2.7. BatchSQLConnectionCreate

Class

Raincode.Batch.Utilities.Database.DatabaseConnection

Field name

BatchSQLConnectionCreate

Strategy

Best non null

Default implementation

Basic implementation does nothing

Plugin API:

System.Data.Common.DbConnection(System.Data.Common.DbConnection DbConnection)

  • DbConnection - The created DbConnection

  • Result - A (possibly updated) DbConnection

Description:

When a batch utility like DSNUTILB open a SQL connection the plugin is called to enable custom operation on connection after the connection creation .

For more details refer to the DB connection plugin documentation.

13.2.8. BatchSQLConnected

Class

Raincode.Batch.Utilities.Database.DatabaseConnection

Field name

BatchSQLConnected

Strategy

Best non null

Default implementation

Basic implementation does nothing

Plugin API:

System.Data.Common.DbConnection(System.Data.Common.DbConnection DbConnection)

  • DbConnection - The opened DbConnection

  • Result - A (possibly updated) DbConnection

Description:

When a batch utility like DSNUTILB open a SQL connection the plugin is called to enable custom operation on connection after the connection is open.

For more details refer to the DB connection plugin documentation.

13.2.9. BatchSQLDisconnect

Class

Raincode.Batch.Utilities.Database.DatabaseConnection

Field name

BatchSQLDisconnect

Strategy

Best non null

Default implementation

Basic implementation does nothing

Plugin API:

System.Data.Common.DbConnection(System.Data.Common.DbConnection DbConnection)

  • DbConnection - The DbConnection to be closed

  • Result - A (possibly updated) DbConnection

Description:

When a batch utility like DSNUTILB open a SQL connection the plugin is called to enable custom operation on connection before the connection close.

For more details refer to the DB connection plugin documentation.

14. Writing utilities

Raincode provides support for developers writing JCL utilities with the following:

  1. A JCL grammar for the PEG parser generator,

  2. Two classes that implement useful functionality for the utilities

  3. Three utility implementations as samples.

The class Raincode.Batch.Utilities.Common.BaseOptions manages command-line options common to all batch utilities.

Table 46. Attributes of BaseOptions
Attributes Description

protected ArgumentSet SupportedArguments

A recognized Argument set is needed to add your arguments.

public Manager CatalogManager

Catalog Manager builds on the given - CatalogConfiguration parameter or on RC_BATCH_CATALOG

public bool ScanOnly {get; set;}
public bool ScantoDB
public string DBConnectString {get; set;}
public string DBDriver {get; private set;}

Some Raincode utilities can run in Scan mode and log information into a repository.

The class Raincode.Batch.Utilities.Common.BaseUtility is the base root class for batch utilities.

Table 47. Attributes of BaseUtility
Attributes Description

protected ActualOptions Options

Options parsed: This class contains a property CatalogManager to be used to access DSN

public static LogSource LogSource

LogSource to be used when using RccoreLib log facilities.

Table 48. Methods of BaseUtility
Method Description

BaseUtility (bool needRuntime)

The class constructor uses a boolean parameter that informs the base class if the utility will use Raincode Stack assembly. If true, path %RCDIR%/bin is added as the assembly resolution path.

protected abstract void Execute()

This is the entry point of your utility. This method is called once all parameters are parsed and CatalogManager is created. This method is abstract and must be defined by the user.

protected static void BasicMain (string[] args)

The method is to be called (most of the time trivially) by the main entry point of the executable. This method takes care of parsing parameters and calls the Execute.

The main class of a utility should look like this:

using Raincode.Batch.Utilities.Common;
using RainCode.Core.CommandLine;
using RainCode.Core.Logging;
using RainCodeLegacyBatchDataset;
using System;
using System.IO;

namespace Raincode.Batch.Utilities
{
    [RCProductGroupAttribute("Raincode.Batch.Utilities")]
    public class MyOptions : BaseOptions
    {
        public MyOptions()
        {
            // Your own options
            SupportedArguments.SupportArg(new StringArg("MyFlag")
            {
                Description = "Your own Option.",
                Action = val => { MyFlag = val; },
                Category = "General"
            });

        }
        public string MyFlag { get; set; }
    }

    public class MyUtility : BaseUtility<MyUtility, MyOptions>
    {
        // Main program entry call BasicMain unless you need special processing
        static void Main(string[] args) => BasicMain(args);

        public MyUtility() : base(needRuntime: false) { }
        protected override void Execute()
        {
            // This is the main procedure of your Utility.
            // The return code should be placed in Environment.ExitCode
            Logger.LogInfo(LogSource, "MyUtility starting");

            // Retrieve your Input in SYSIN
            Logger.LogTrace(LogSource, "Reading SYSIN");
            DataSet systsin = UtilityOptions.CatalogManager.FindKnowDDName("SYSIN");

            if (systsin == null)
            {
                throw new FileNotFoundException("Input file SYSIN not found");
            }
			//TODO add your utility code here
            throw new NotImplementedException("TODO not implemented!");
        }
    }
}

The Sample directory provides you with the implementation of three utilities you may use as a template for your utilities.

15. Samples

15.1. Creating and running a Job from C#

The following sample describes how to create a job from C# code and execute it using the SubmitRunner class from the Raincode.Batch.Submit assembly.

15.1.1. Job Setup and Execution

The first step in creating a job is to allocate a Catalog Manager object. This is used to generate the unique Job ID and is used throughout the execution of the job to query and manage datasets. Next, the job object is built up, and finally the SubmitRunner.Execute() method is called to execute the job.

Below is a sample job being constructed:

var catMan = new Manager();

Job job = new Job("MYJOB",catMan,catMan.AllocateJob());
var step1 = ProgramStep.CreateProgramStep("STEP1","IEFBR14",job.ID);
job.AddStep(step1);
step1.AddDD(new DD()
{
 RecordFormat = RecordFormat.FB,
 DSN = "TEST.FILE",
 Disposition = new Disposition()
    {
		Mode = DispositionStatus.MOD,
		Normal = DispositionType.CATLG,
		Abnormal = DispositionType.DELETE
	},
RecordLength = 80,
Volume = "DEFAULT"
});

var options = new Submit.Options();
var ret = Submit.SubmitRunner.Execute(new Submit.Options(), job);

It is important to remember that the step is added to the job object by calling AddStep. This is so the step can be configured to run in the job correctly. Also, note that AddDD is called on the step to add a DD object instead of adding directly to the collection. This is required so the DD can be properly configured for the step.

15.2. Serializing a Job for Remote Execution

To serialize a job for remote execution, call the Job.SerializeJob() method passing in a constructed Job object that has not been executed yet. It will return a JSON encoded string that can be sent to another machine (via web service, file, or other IPC mechanism). Deserialization is handled by Job.DeserializeJob(), however additional setup is required to make it ready to execute.

The code below shows an example:

// Job is created from C# or from parsed JCL

var serialized = Job.SerializeJob(job);

// The serialized variable now contains the string representing the job

//On the other machine/instance:

var deserialized = Job.DeserializeJob(serialized);

var catMan = new Manager();

jobId = catMan.AllocateJob();

deserialized.ResetState(catMan,jobId);

Submit.SubmitRunner.Execute(new Submit.Options(), deserialized);

15.3. Customizing Submit

The submit process can be customized by implementing a console application that creates an instance of the Options() class to parse the command-line parameters, then call SubmitRunner.Execute() and return the return code.

Below is a sample implementation:

namespace Raincode.Batch.Submit
{
  internal class Program
    {
        private static int Main(string[] args)
        {
            var opts = new Options();
			opts.Parse(args);
            return SubmitRunner.Execute(opts);
		}

    }
}

15.4. Customizing Logging

The batch runtime process uses the RainCode.Core.Logging.Logger class to route log messages to the appropriate source. By default, a logger is registered that outputs messages to the default Trace listener. Additionally, the -LogToConsole option for submit will register a ConsoleLogger that will output log events to the console. Output can be captured by adding a .NET configuration section to the submit.exe.config (or appropriate application configuration file), such as:

<system.diagnostics>
    <trace autoflush="true" indentsize="4">
      <listeners>
     <add name="myListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="TextWriterOutput.log"/>
				<remove name="Default"/>
			</listeners>
	</trace>
</system.diagnostics>

Alternatively, a custom logging class can be registered in a custom Submit executable. For instance, this implementation of Submit.exe adds a ConsoleLogger source:

namespace Raincode.Batch.Submit
{
  internal class Program
  {
	private static int Main(string[] args)
	 {
		RainCode.Core.Logging.Logger.CreateAndRegister<RainCode.Core.Logging.ConsoleLogger>();
		  var opts = new Options();
		  opts.Parse(args);
		  return SubmitRunner.Execute(opts);
	 }
   }

}

To control the log level that is set, refer to the -LogLevel command-line option.

15.5. JCL Containerization

In the sample RaincodeJCLWrapper, the steps to containerize a JCL are demonstrated. This involves creating a REST API that accepts input parameters such as JobName and JobId, and returns the JobId of the submitted job as output.

apicontroller
Figure 35. ApiController

As shown below, the jclOptions, the path for the file storage, the path for the catalog manager and jobid are defined. In the later part, submitRunner.Execute is called with the jclOptions to run a JCL.

invokesubmitrunner
Figure 36. Invoke Submit Runner

For more details, refer to Submit.

15.5.1. Prerequisites

  • Raincode JCL compiler image

  • Raincode JCL runner image

  • Raincode license - Must be added to the RaincodeJCLWrapper project.

  • Docker Desktop

For more details on loading the Raincode JCL compiler and JCL runner image, refer to load the desired image.

15.5.2. Build Docker Image

The screenshot below is a dockerfile that creates an image to containerize the JCL runner.

dockerfilescreenshot
Figure 37. A docker file

Through the Visual Studio solution, open the developer command prompt and navigate to the location of the dockerfile and issue the command docker build, as shown in the screenshot below:

dockerbuild
Figure 38. Docker Build

Once the build is successful, it will generate an image. The image can be seen through the command prompt, as shown in the screenshot below.

images
Figure 39. Images
Make sure that the docker desktop is running.

15.5.3. Run Docker container

The docker run command runs a container from the image and runs on the port specified (8080).

The file volume mount option lets us mount a local machine volume to a particular path inside the container so that the container can access the file volume.

As the screenshot below shows, the FileStorage volume has been successfully mounted from the local system to the container’s app/FileStorage location.

Mountvolume
Figure 40. Container running on port 8080 - Command Prompt
joblogonthecontainer
Figure 41. Container running on port 8080 - Docker Desktop

After the file mount, the container is able to access files from the local machine. The container can access the Catalog, Jcls and Program executables.

contentsofthecontainer2
Figure 42. Contents of the container

Below is the sample Raincode.Catalog.xml that describes the configuration for the Submit runner. For more details, refer to the Catalog configuration.

raincodecatalogxml
Figure 43. Raincode Catalog XML

15.5.4. Run a sample JCL

The above running docker container is called to execute JCLHELLO.JCL, which invokes HELLO.cob to print a SIMPLE HELLO WORLD message.

JCL
Figure 44. A JCL file
COBOL
Figure 45. A COBOL file

Since the jclwrapper container is running on port 8080, the API must be invoked using an HTTP client such as Postman. The screenshot below shows that the request to execute JCLHELLO.JCL was sent and the job id JOB0000000001 was received as a response.

JCLincontainer
Figure 46. JCL in postman

Also, you can see the job log from the container.

jobloginterminal
Figure 47. Joblog of the terminal

You can examine the output on the local system from the folder SYSOUT. You can check MSGLOG.txt for the details.

joblogonthelocalsystem
Figure 48. Joblog on the local system

If you look at the app/Filestorage location inside the container, you see the necessary folder created by the Submit runner and the job log for the JCL, as shown in the screenshot below.

contentsofthecontainer1
Figure 49. Content of the container

16. Telemetry

16.1. Introduction

This section describes Raincode’s approach to Telemetry across all relevant products.

For the sake of readability of the documentation, this section is repeated identically in the following manuals: QIX, IMSql, and JCL.

16.1.1. What is Telemetry

According to Wikipedia, Telemetry is the automatic process of measuring and transmitting data for the purpose of monitoring applications and assessing their health and performance.

This definition implies the clear separation between the production of this continuous stream of data and the collection, summarization, storage, etc., of this data. As a response to this separation, the OpenTelemetry standard has emerged, enabling a vibrant market for visualization and monitoring tools. It provides a single, open-source standard and a set of technologies to capture and export metrics, traces, and logs from cloud-native applications and infrastructure.

16.1.2. How about Raincode

Telemetry applies to the subset of Raincode’s products that include a runtime component:

  • QIX, Raincode’s CICS emulator

  • IMSql, Raincode’s IMS emulator (and in the context of Telemetry, focusing on the IMS/TM part of this product)

  • Raincode JCL.

While very different in functionality, these products share the ability to send events that can be used to monitor the health and performance of the running processes.

While the Raincode Console can be used to manage the static aspects of the configuration of these products and some more dynamic aspects (inspecting IMS/TM queues, for instance), it does not offer any telemetry capabilities. This is not an oversight: the Raincode product line is designed to connect to third-party solutions for Telemetry instead.

Further, the section below explains how the Raincode products mentioned above can be configured to external telemetry services for monitoring, visualization, alerts, and more.

16.2. In practice

The Raincode products are agnostic as per the telemetry platform (or even Telemetry standard) they will connect to.

Using user-defined plugins, one has full control over how events produced by the products (starting or stopping a JCL, QIX transactions, etc.) are handled, what to connect to, etc.

The QIX, IMSql, and Raincode JCL distributions include a plugin that connects to an OpenTelemetry endpoint, which can be easily replaced or extended for more functionality or to connect to an entirely different platform if necessary.

16.2.1. Event Structure

The events produced by all Raincode products follow a consistent naming convention. The event names are made of three parts, separated by colons, according to the following pattern:

  • Product: The name of the product, forced in lower case, e.g. qix or ims

  • Name: The type object the event is about, e.g. transaction or aplitdli

  • Verb: The action that was done on that object, e.g. start, stop, abort

For instance, valid event names include:

  • qix:transaction:start

  • ims:transaction:stop

This simple scheme allows optimal flexibility when filtering events by product, object, action or any combination thereof.

Table 49. The telemetry events
Event Arguments Description

ims:transaction:start

the transaction code

Start of an IMS transaction

ims:transaction:stop

the transaction code
the return code

End of an IMS transaction

ims:appltdli:start

the function

Start of a IMS call (EXEC DLI, CBLTDLI, PLITDLI, CEETDLI, ASMTDLI) using a DB PCB

ims:appltdli:stop

the function

End of a IMS call (EXEC DLI, CBLTDLI, PLITDLI, CEETDLI, ASMTDLI) using a DB PCB

ims:appltdli_io:start

the function

Start of a IMS call (EXEC DLI, CBLTDLI, PLITDLI, CEETDLI, ASMTDLI) using a IO PCB

ims:appltdli_io:stop

the function

End of a IMS call (EXEC DLI, CBLTDLI, PLITDLI, CEETDLI, ASMTDLI) using a IO PCB

ims:appltdli_alt:start

the function

Start of a IMS call (EXEC DLI, CBLTDLI, PLITDLI, CEETDLI, ASMTDLI) using a alternate PCB

ims:appltdli_alt:stop

the function

End of a IMS call (EXEC DLI, CBLTDLI, PLITDLI, CEETDLI, ASMTDLI) using a alternate PCB

qix:transaction:start

the transaction code

Start of on CICS transaction

qix:transaction:stop

the transaction code
the return code

End of on CICS transaction

batch:job:preexecute

the name of the job

Start of a job (JCL)

batch:job:postexecute

the name of the job
the return code

End of a job (JCL)

batch:step:preexecute

the name of the step

Start of a step

batch:step:postexecute

the name of the step
the return code

End of a step

16.2.2. The Telemetry plugin

The plugin provides a single interface for events behind which the user can customize the filtering and connection to the telemetry API of choice. This interface is made using a single method.

LogTelemetryEvent(name, args…)

To which the first parameter will always be the event name, and the following parameters will depend on the event itself.

LogTelemetryEvent("qix:transaction:start", Transaction.ID);
LogTelemetryEvent("qix:transaction:stop", Transaction.ID, transactionResult.Error);

If only a subset of the events must be reacted to, one can use an appropriate filtering regular expression, taking advantage of the naming convention described above.

        public void LogTelemetryEvent(string eventName, params string[] eventData){
            switch (eventName)
            {
                case "ims:transaction:start":
                    StartIMSqlTransactionTelemetry(eventData[0]);
                    break;
                case "ims:transaction:stop":
                    StopIMSqlTransactionTelemetry(eventData[0], eventData[1]);
                    break;
                case "ims:appltdli:start":
                    StartAppltdliTelemetry(eventData[0]);
                    break;
                case "ims:appltdli:stop":
                    StopAppltdliTelemetry(eventData[0]);
                    break;
                default:
                    break;
            }
        }
The sample telemetry plugin can be found at %RCDIR%\plugins\AppInsights.

16.2.3. Using a plugin: command line

Providing the telemetry plugin follows the same options as providing any plugin to an application.

Use -Plugin to provide a path to an assembly.

Submit.exe -Plugin=<path to assembly>

Or you can use -PluginPath to provide a path to a folder where all the assemblies will be scanned for plugins.

Submit.exe -PluginPath=<path to folder>

The screenshot below was captured by connecting Raincode JCL to .NET Aspire® and using Application Insight for visualization.

telemetry1
Figure 50. Central telemetry graph

17. Raincode dual SQL runtime- Introduction

This document describes how to use the Raincode dual SQL runtime (also known as RainCodeLegacySqlDB2OleDbSqlServer) across multiple Raincode products. The dual SQL runtime targets both SQL Server and Db2, using the Microsoft OLE DB Provider for DB2. It can leverage Microsoft Distributed Transaction Coordinator (MSDTC, or DTC) to allow distributing the transaction and guarantee transactional integrity between SQL Server and Db2.

17.1. Prerequisites

17.2. RainCodeLegacySqlDB2OleDbSqlServer

This is an SQL runtime implementation compatible with the Raincode Stack suite. It is designed to enable connections to both SQL Server and Db2, allowing a single COBOL program to work with both databases in the same execution.

It is not a generic SQL runtime that can be used to target any SQL database; it is confined to targeting SQL Server and Db2.

The rest of this section will explain how RainCodeLegacySqlDB2OleDbSqlServer works. Later sections will explain how to configure and use it in the Raincode product suite with the help of samples.

SQL Server is the main database, and when the program starts, a connection is opened using the connection string specified in the configuration file (see Configuration file). All EXEC SQL statements will be run against SQL Server until it encounters an EXEC SQL CONNECT TO statement.

When an EXEC SQL CONNECT TO statement is executed, RainCodeLegacySqlDB2OleDbSqlServer establishes a connection to Db2 using the name specified in the CONNECT TO statement (see the Configuration file for details on how to configure this). Once the connection is established, all subsequent EXEC SQL statements will be executed against Db2, until a new CONNECT TO, SET CONNECTION or CONNECT RESET command is issued.

SET CONNECTION will switch to a previously opened Db2 connection.

CONNECT RESET will set the Db2 connection aside (not closed), and all subsequent SQL queries will be run against SQL Server. Calling CONNECT RESET always causes RainCodeLegacySqlDB2OleDbSqlServer to switch back to using the SQL Server connection.

17.3. Instantiating RainCodeLegacySqlDB2OleDbSqlServer

The RainCodeLegacySqlDB2OleDbSqlServer requires two or more connection strings: one for SQL Server and one or more for Db2. To achieve this, RainCodeLegacySqlDB2OleDbSqlServer requires a configuration file providing, among other things, the necessary connection strings.

In the Raincode Stack suite, wherever a connection string can be specified, and when using RainCodeLegacySqlDB2OleDbSqlServer, the path to the configuration file should be specified instead. For instance, in Raincode JCL, RcDbConnections.csv should have a plan specifying RainCodeLegacySqlDB2OleDbSqlServer as the SQL target, and instead of a connection string, the path to a configuration file, like so:

DUALPLAN,RainCodeLegacySqlDB2OleDbSqlServer,DualRuntimeConfig.cfg

17.3.1. Configuration file

The format of this file is subject to change in the future.

The configuration is an XML file defining the following attributes:

  • SqlServerConnectionString: A mandatory connection string for SQL Server.

  • XXXX_ConnectionString: An optional connection string for Db2. Replace XXXX with the name passed to the CONNECT TO in the COBOL program. You can specify multiple such connection strings, one for each Db2 instance that the program can connect to.

  • UseDTC: An optional boolean flag specifying whether the dual runtime should use DTC (Distributed Transaction Coordinator).

    Valid values are true and false (case insensitive). The default value is false.

    In practice, this suppresses any ambient transaction by instantiating a TransactionScope with option TransactionScopeOption.Suppress. Commits and rollbacks are handled separately for each database used.

    When UseDTC="true", make sure to specify Units of Work=DUW;AutoCommit=False; in the OLE DB for Db2 connection string, otherwise the distributed transaction will fail with exception System.InvalidOperationException: The ITransactionLocal interface is not supported by the 'DB2OLEDB' provider. Local transactions are unavailable with the current provider. when enlisting the Db2 connection into the current transaction.
    When UseDTC="false", make sure to specify Units of Work=RUW;AutoCommit=False; in the OLE DB for Db2 connection string, otherwise you’ll get exception System.InvalidOperationException: The ITransactionLocal interface is not supported by the 'DB2OLEDB' provider. Local transactions are unavailable with the current provider. when querying Db2 for the first time.

17.3.2. Samples

Three sample examples are provided to illustrate how the dual runtime integrates with the different Raincode products:

  1. Raincode JCL

  2. Raincode QIX

  3. Raincode Stored Procedure Runner

These can be found in %RCDIR%\samples\Dual SQL runtime

Sample batch job: batch sample

This sample shows how to run a batch job with the dual SQL runtime. It consists of a single COBOL program that showcases the dual SQL runtime and distributed transactions.

Description of files
  • dual.jcl: A JCL script used to execute a batch job. It starts the program DUALCOB using the plan DUALPLAN.

    //SIMPLE   JOB  CLASS=A,MSGCLASS=C
    //STEP0 EXEC PGM=IKJEFT01
    //SYSTSIN  DD *
      RUN PROGRAM(DUALCOB) PLAN(DUALPLAN)
      END
    /*
  • RcDbConnections.csv: A database connections file mapping DUALPLAN to the RainCodeLegacySqlDB2OleDbSqlServer and the configuration file for said runtime.

    DUALPLAN,RainCodeLegacySqlDB2OleDbSqlServer,DualRuntimeConfig.cfg
  • DualRuntimeConfig.cfg: An XML configuration file, specific to DualRuntimeConfig.cfg. It’s contains all necessary connection strings to be used by the dual SQL runtime.

    <RainCodeLegacySqlDDB2OleDbSqlServer
      SqlServerConnectionString="..."
      DB2SRV_ConnectionString="..."
      />
  • DUALCOB.cob: A COBOL program that connects to Db2 and performs the following SQL queries (not necessarily in this order):

    1. SELECT on SQL Server

    2. SELECT on Db2

    3. INSERT on Db2

    4. CONNECT TO

    5. SET CONNECTION

    6. CONNECT RESET

  • sqlserver.ddl and db2.ddl: the DDLs for creating the tables used in DUALCOB.COB.

Running the sample
  1. Update the connection strings in DualRuntimeConfig.cfg

  2. Create the required tables in SQL Server and Db2 using the provided DDL files

  3. Compile the program by running ./compile.ps1

  4. Execute the program with ./run.ps1

    After the run completes, you should see the following in the log output:

BEGIN
SQL Server SELECT:
SQLCODE: 0000000000
WS-C2: initial sql server data
--------------
Connect to 'DB2SRV  ':
SQLCODE: 0000000000
--------------
DB2 Init data
SQLCODE: 0000000000
--------------
DB2 SELECT:
SQLCODE: 0000000000
C1: initial db2 data
--------------
DB2 INSERT:
SQLCODE: 0000000000
--------------
DB2 SELECT:
SQLCODE: 0000000000
C1: John Dough
--------------
SQLCODE: 0000000000
SQL Server SELECT:
SQLCODE: 0000000000
WS-C2: initial sql server data
--------------
SET CONNECTION:
SQLCODE: 0000000000
--------------
DB2 INSERT:
SQLCODE: 0000000000
--------------
DB2 SELECT:
SQLCODE: 0000000000
C1: John Dough
--------------
END
Sample QIX transaction: qix sample

This sample shows how to run a Raincode QIX transaction, running a COBOL program showcasing the dual SQL runtime and distributed transaction.

Description of files
  • createregion.ps1: Edits the file to add connection strings and run to create the QIX region

  • buildbms.ps1: PowerShell script to compile the screen

  • MMENU.bms: the map used by the transaction

  • compile.ps1: PowerShell script to compile the COBOL program

  • DualRuntimeConfig.cfg: configuration file for the RainCodeLegacySqlDB2OleDbSqlServer SQL runtime. It’s an XML file containing all necessary connection strings to be used by the dual SQL runtime.

    <RainCodeLegacySqlDDB2OleDbSqlServer
      SqlServerConnectionString="..."
      DB2SRV_ConnectionString="..."
      />
  • DUALCOBQIX.cob: A COBOL program that connects to Db2 and performs the following SQL queries (not necessarily in this order):

    1. SELECT on SQL Server

    2. SELECT on Db2

    3. INSERT on Db2

    4. CONNECT TO

    5. SET CONNECTION

    6. CONNECT RESET

  • sqlserver.ddl and db2.ddl: the DDLs for creating the tables used in DUALCOB.COB.

  • startqix.ps1: PowerShell script to start the Raincode QIX region

Running the sample
  1. Update the application connection strings in DualRuntimeConfig.cfg.

  2. Update the QIX connection string in createregion.ps1 and startqix.ps1.

  3. Create the required tables in SQL Server and Db2 using the provided DDL files.

  4. Compile the map with buildbms.ps1

  5. Compile the program with compile.ps1

  6. Run startqix.ps1

  7. In a 3270 terminal emulator, connect to the QIX terminal server.

    After the run completes, you should see the following on the terminal emulator:

 MYTR                           CUSTOMER CATALOG                       Raincode
 TERMID: DEMO                                                          08:46


 SQL Server SELECT: SQLCODE = 00000000, C2 = initial sql server data
 Connect to: DB2SRV  , SQLCODE = 00000000
 DB2 Init data (DELETE): SQLCODE = 00000000
 DB2 Init data (INSERT): SQLCODE = 00000000
 DB2 SELECT: SQLCODE = 00000000, C1 = initial db2 data
 DB2 INSERT: SQLCODE = 00000000
 DB2 SELECT: SQLCODE = 00000000, C1 = John Dough
 CONNECT RESET SQLCODE = 00000000
 SQL Server SELECT: SQLCODE = 00000000, C2 = initial sql server data
 SET CONNECTION: SQLCODE = 00000000







 DB2 INSERT: SQLCODE = 00000000
 F3: Exit  ENTER: Process
Sample COBOL stored procedure: sp sample

This sample shows how to run a COBOL stored procedure using the dual SQL runtime, in the context of the Raincode Stored Procedure Runner.

Description of files
  • compile.ps1: A PowerShell script to compile the COBOL program and generate the C# helper program.

  • config.xml: An XML configuration file for the Raincode Stored Procedure Runner. In the context of using the dual sql runtime, the most important lines are these:

      SqlRuntime="RainCodeLegacySqlDB2OleDbSqlServer"
      SqlRuntimeConnectionString="path_to_DualRuntimeConfig.cfg"

    The other attributes ProgramsPath, HelpersPath should be filled according to Raincode Stored Procedure Runner Configuration file

  • DualRuntimeConfig.cfg: configuration file for the RainCodeLegacySqlDB2OleDbSqlServer SQL runtime. It’s an XML file containing all necessary connection strings to be used by the dual SQL runtime. In the context of running a COBOL stored procedure, the UseDTC attribute is set to false.

    <RainCodeLegacySqlDDB2OleDbSqlServer
      SqlServerConnectionString="..."
      DB2SRV_ConnectionString="..."
      UseDTC="false"
      />
  • DUALCOBSP.cob: A COBOL program that connects to Db2 and performs the following SQL queries (not necessarily in this order):

    1. SELECT on SQL Server

    2. SELECT on Db2

    3. INSERT on Db2

    4. CONNECT TO

    5. SET CONNECTION

    6. CONNECT RESET

  • sqlserver.ddl and db2.ddl: the DDLs for creating the tables used in DUALCOB.COB

  • startqix.ps1: A PowerShell script to start the Raincode QIX region

Running the sample

Run compile.ps1 to generate the helper program and the .dll file of the COBOL program. Then, follow instructions at Deploying a COBOL stored procedure to deploy the COBOL stored procedure.

Specifically, udpate $env:RCDIR\StoredProcedureRunner\config.xml with appropriate values, using the config.xml included in this sample as reference.

The COBOL stored procedure can be tested by running the following T-SQL script in SQL Server Management Studio, for example.

DECLARE	@return_value int

EXEC	@return_value = [dbo].[DUALCOBSP]
		@P0 = 42

SELECT	'Return Value' = @return_value

GO

After the successful execution, you should see the following output in the Messages tab:

BEGIN2
P1: 000000042
SQL Server SELECT:
SQLCODE: 0000000000
WS-C2: initial sql server data
--------------
Connect to 'DB2SRV  ':
SQLCODE: 0000000000
--------------
DB2 SELECT:
SQLCODE: 0000000000
C1: John Dough
--------------
DB2 INSERT:
SQLCODE: 0000000000
---------
STDOUT message(s) from external script:
-----
DB2 SELECT:
SQLCODE: 0000000000
C1: John Dough
--------------
SQLCODE: 0000000000
SQL Server SELECT:
SQLCODE: 0000000000
WS-C2: initial sql server data
--------------
SET CONNECTION:
SQLCODE: 0000000000
--------------
DB2 INSERT:
SQLCODE: 0000000000
--------------
DB2 SELECT:
SQLCODE: 0000000000
C1: John Dough
--------------
END

17.4. Troubleshooting

17.4.1. System.InvalidOperationException: The 'DB2OLEDB' provider is not registered on the local machine.

Cause: The Microsoft OLE DB Provider for Db2 is not installed.

17.4.2. System.Transactions.TransactionManagerCommunicationException: Network access for Distributed Transaction Manager (MSDTC) has been disabled.

Cause: MSDTC network access is disabled.

Fix: Enable MSDTC network access in Component Services

17.4.3. Error: MSDTC was unable to read its configuration information. (0x8004D027)

Cause: when running a COBOL stored procedure with the dual sql runtime, the Db2 connection is enlisted in the TransactionScope, causing MSDTC to kick in. MSDTC does not work in SQL Server Language Extensions (the environment used to run a COBOL stored procedure).

Fix: Disable DTC by specifying xml attribute UseDTC="false" in the configuration file.

17.4.4. System.InvalidOperationException: The ITransactionLocal interface is not supported by the 'DB2OLEDB' provider. Local transactions are unavailable with the current provider.

Cause: There’s a mismatch in the configuration file.

Fix:

  • When DTC is used, make sure you specify Units of Work=DUW in the Db2 connection string.

  • Without DTC, make sure you specify Units of Work=RUW in the Db2 connection string.

Appendix A: The repository

This section overviews the Raincode legacy compilers, Raincode IMSql and Raincode JCL JOB repository. The repository contains detailed information on the tables gathered by the legacy compilers, IMSql and JCL JOBs. The repository is structured into several SQL tables and stored in a SQLite database (.DB3 file).

The repository can be explored using DB Browser for SQLite®, which lets you see the database structure, browse data, execute SQL queries, and provide many more options.

For the sake of readability of the documentation, this section is repeated identically in the following manuals: Stack, IMSql, and JCL.

Some actions that can be performed using DB Browser are:

  • Exploring the database structure

For example, as illustrated in the screenshot below, the RC_PROGRAM table contains information about program files that have been analyzed by Raincode legacy compilers.

RI 2
Figure 51. DB Browser-Database structutre
  • Browsing data

For example, as illustrated in the screenshot below, users can explore the data within the RC_PROGRAM table.

RI 3
Figure 52. DB Browser- Browse data
  • Executing SQL queries

For example, users can write queries to investigate the database content. The query in the screenshot below displays a list of programs for which the Raincode compiler reported zero errors.

RI 4
Figure 53. DB Browser-Execute SQL

Raincode also provides a PowerBI template called Raincode Insight, to visualise the repository’s contents.

Below are some screenshots from a sample repository captured using the Raincode Insight tool.

The first screenshot illustrates the Raincode Insight dashboard.

RI 5
Figure 54. Raincode Insight - Dashboard

The second screenshot displays the general statistics of the portfolio.

RI 1
Figure 55. Raincode Insight- Statistics tab

Here are the links to the available Raincode repositories:

A.1. JCL JOB repository

A.1.1. RC_JCL_JOB table

The RC_JCL_JOB table holds information about the submitted JCL job.

Table 50. RC_JCL_JOB columns
Column Type Description

RC_ID

Int32

The record identifier for JCL job. RC_ID is the key of this record.

RC_JOB_NAME

String

Name of submitted JCL job

RC_JOB_PATH

String

JCL job path

RC_JOB_COND

String

JCL job conditions. For example:(0,GT)

RC_JOB_TIME

String

Time when the job was submitted

RC_JOB_SCAN_DUR

String

Time taken to scan JCL (milliseconds)

A.1.2. RC_JCL_PGM_STEP table

The RC_JCL_PGM_STEP table holds information about the program steps of submitted jobs.

Table 51. RC_JCL_PGM_STEP columns
Column Type Description

RC_ID

Int32

Foreign key to entry in RC_JCL_JOB. Identifies the program on which these data apply.

RC_SEQ

Int32

The pair of RC_ID and RC_SEQ serves as the primary key for this record

RC_STEP_NAME

String

Name of JCL job step

RC_PROG_NAME

String

Name of the program to be executed in JCL step

RC_PROG_PARAMS

String

Program parameters

RC_PROG_COND

String

Program conditions

RC_PROG_RUNNER

String

The utility used to run the program. For example, IKJEFT, DFSRRC00.

RC_PROG_EXE

String

Program executable

A.1.3. RC_JCL_PROC_STEP table

The RC_JCL_PROC_STEP table holds information about the procedure steps of submitted jobs.

Table 52. RC_JCL_PROC_STEP columns
Column Type Description

RC_ID

Int32

Foreign key to entry in RC_JCL_JOB. Identifies the program on which these data apply.

RC_SEQ

Int32

The pair of RC_ID and RC_SEQ serves as the primary key for this record

RC_STEP_NAME

String

Name of JCL job step

RC_PROC_NAME

String

Name of the procedure to be executed in JCL step

RC_PROC_PARAMS

String

Procedure parameters

RC_PROC_COND

String

Procedure conditions

RC_PROC_INPUT_CARDS

String

Procedure source code

A.1.4. RC_JCL_DD table

The RC_JCL_DD table holds information about data definitions of submitted jobs.

Table 53. RC_JCL_DD columns
Column Type Description

RC_ID

Int32

Foreign key to entry in RC_JCL_JOB. Identifies the program on which these data apply.

RC_SEQ

Int32

The pair of RC_ID and RC_SEQ serves as the primary key for this record

RC_DD_NAME

String

Data definition name

RC_DSN_NAME

String

Dataset name

RC_DISPOSITION

String

Data definition disposition

RC_IS_DUMMY

Boolean

Indication if DD is used as DUMMY dataset

RC_INSTREAM_DATA

String

Instream data content

RC_PROG_STEP_REF

Int32

DD reference to parent program step RC_SEQ number (-1 means no reference)

RC_PROC_STEP_REF

Int32

DD reference to parent procedure step RC_SEQ number (-1 means no reference)

A.1.5. RC_JCL_ERR table

The RC_JCL_ERR table holds information about errors of submitted jobs.

Table 54. RC_JCL_ERR columns
Column Type Description

RC_ID

Int32

Foreign key to entry in RC_JCL_JOB. Identifies the program on which these data apply.

RC_SEQ

Int32

The pair of RC_ID and RC_SEQ serves as the primary key for this record

RC_ERR_TYPE

String

JCL error type

RC_ERR_MSG

String

Error message including the cause of an error

RC_ERR_LINE

Int32

The line number where the error occurs

A.1.6. RC_JCL_VAR table

The RC_JCL_VAR table holds information about the variables used in the submitted jobs.

Table 55. RC_JCL_VAR columns
Column Type Description

RC_ID

Int32

Foreign key to entry in RC_JCL_JOB. Identifies the program on which these data apply.

RC_SEQ

Int32

The pair of RC_ID and RC_SEQ serves as the primary key for this record

RC_VAR_NAME

String

The name of the variable

RC_VAR_VALUE

String

The value of the variable. If the variable is not found, the value is the name of the variable prefixed by v.

RC_VAR_FOUND

Boolean

This column contains only 1 or 0. 1 if the value of the variable is known, 0 otherwise

RC_VAR_CONTROLM

Boolean

1 if it’s a Control-M variable

A.1.7. RC_UTILITIES_PARSING_STATUS table

The RC_UTILITIES_PARSING_STATUS table holds information about the SYSIN parsing done by the utilities (SORT, IKJEFT, …​).

Table 56. RC_UTILITIES_PARSING_STATUS columns
Column Type Description

RC_ID

Int32

Foreign key to entry in RC_JCL_JOB. Identifies the program on which these data apply.

RC_SEQ

Int32

The pair of RC_ID and RC_SEQ serves as the primary key for this record

RC_STEP_NAME

String

The name of the step

RC_UTILITY_NAME

String

The name of the utility

RC_COMMAND_TEXT

String

The command sent to the utility (usually the SYSIN)

RC_STATUS_TEXT

String

The error message, if any

RC_COLUMN_NUMBER

Int32

The column number where the error occurs

RC_COMMAND_PARSE_STATUS

Boolean

Returns 1 if parsing is successful and 0 if there are parsing errors

Appendix B: Lists of tables and figures in document

This appendix includes the automated lists of the tables and figures available in this document; placed in this location, to allow you to gain access to core information regarding Raincode JCL more readily up front, and as an aide-memoire.